OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/loop-analysis.h" | 5 #include "src/compiler/loop-analysis.h" |
6 | 6 |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/node.h" | 8 #include "src/compiler/node.h" |
9 #include "src/compiler/node-marker.h" | 9 #include "src/compiler/node-marker.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
11 #include "src/zone.h" | 11 #include "src/zone.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace compiler { | 15 namespace compiler { |
16 | 16 |
17 typedef uint32_t LoopMarks; | 17 #define OFFSET(x) ((x)&0x1f) |
18 | 18 #define BIT(x) (1u << OFFSET(x)) |
| 19 #define INDEX(x) ((x) >> 5) |
19 | 20 |
20 // TODO(titzer): don't assume entry edges have a particular index. | 21 // TODO(titzer): don't assume entry edges have a particular index. |
21 // TODO(titzer): use a BitMatrix to generalize this algorithm. | |
22 static const size_t kMaxLoops = 31; | |
23 static const int kAssumedLoopEntryIndex = 0; // assume loops are entered here. | 22 static const int kAssumedLoopEntryIndex = 0; // assume loops are entered here. |
24 static const LoopMarks kVisited = 1; // loop #0 is reserved. | |
25 | 23 |
26 | 24 |
27 // Temporary information for each node during marking. | 25 // Temporary information for each node during marking. |
28 struct NodeInfo { | 26 struct NodeInfo { |
29 Node* node; | 27 Node* node; |
30 NodeInfo* next; // link in chaining loop members | 28 NodeInfo* next; // link in chaining loop members |
31 LoopMarks forward; // accumulated marks in the forward direction | |
32 LoopMarks backward; // accumulated marks in the backward direction | |
33 LoopMarks loop_mark; // loop mark for header nodes; encodes loop_num | |
34 | |
35 bool MarkBackward(LoopMarks bw) { | |
36 LoopMarks prev = backward; | |
37 LoopMarks next = backward | bw; | |
38 backward = next; | |
39 return prev != next; | |
40 } | |
41 | |
42 bool MarkForward(LoopMarks fw) { | |
43 LoopMarks prev = forward; | |
44 LoopMarks next = forward | fw; | |
45 forward = next; | |
46 return prev != next; | |
47 } | |
48 | |
49 bool IsInLoop(size_t loop_num) { | |
50 DCHECK(loop_num > 0 && loop_num <= 31); | |
51 return forward & backward & (1 << loop_num); | |
52 } | |
53 | |
54 bool IsLoopHeader() { return loop_mark != 0; } | |
55 bool IsInAnyLoop() { return (forward & backward) > kVisited; } | |
56 | |
57 bool IsInHeaderForLoop(size_t loop_num) { | |
58 DCHECK(loop_num > 0); | |
59 return loop_mark == (kVisited | (1 << loop_num)); | |
60 } | |
61 }; | 29 }; |
62 | 30 |
63 | 31 |
64 // Temporary loop info needed during traversal and building the loop tree. | 32 // Temporary loop info needed during traversal and building the loop tree. |
65 struct LoopInfo { | 33 struct LoopInfo { |
66 Node* header; | 34 Node* header; |
67 NodeInfo* header_list; | 35 NodeInfo* header_list; |
68 NodeInfo* body_list; | 36 NodeInfo* body_list; |
69 LoopTree::Loop* loop; | 37 LoopTree::Loop* loop; |
70 }; | 38 }; |
71 | 39 |
72 | 40 |
73 static const NodeInfo kEmptyNodeInfo = {nullptr, nullptr, 0, 0, 0}; | |
74 | |
75 | |
76 // Encapsulation of the loop finding algorithm. | 41 // Encapsulation of the loop finding algorithm. |
77 // ----------------------------------------------------------------------------- | 42 // ----------------------------------------------------------------------------- |
78 // Conceptually, the contents of a loop are those nodes that are "between" the | 43 // Conceptually, the contents of a loop are those nodes that are "between" the |
79 // loop header and the backedges of the loop. Graphs in the soup of nodes can | 44 // loop header and the backedges of the loop. Graphs in the soup of nodes can |
80 // form improper cycles, so standard loop finding algorithms that work on CFGs | 45 // form improper cycles, so standard loop finding algorithms that work on CFGs |
81 // aren't sufficient. However, in valid TurboFan graphs, all cycles involve | 46 // aren't sufficient. However, in valid TurboFan graphs, all cycles involve |
82 // either a {Loop} node or a phi. The {Loop} node itself and its accompanying | 47 // either a {Loop} node or a phi. The {Loop} node itself and its accompanying |
83 // phis are treated together as a set referred to here as the loop header. | 48 // phis are treated together as a set referred to here as the loop header. |
84 // This loop finding algorithm works by traversing the graph in two directions, | 49 // This loop finding algorithm works by traversing the graph in two directions, |
85 // first from nodes to their inputs, starting at {end}, then in the reverse | 50 // first from nodes to their inputs, starting at {end}, then in the reverse |
86 // direction, from nodes to their uses, starting at loop headers. | 51 // direction, from nodes to their uses, starting at loop headers. |
87 // 1 bit per loop per node per direction are required during the marking phase. | 52 // 1 bit per loop per node per direction are required during the marking phase. |
88 // To handle nested loops correctly, the algorithm must filter some reachability | 53 // To handle nested loops correctly, the algorithm must filter some reachability |
89 // marks on edges into/out-of the loop header nodes. | 54 // marks on edges into/out-of the loop header nodes. |
90 class LoopFinderImpl { | 55 class LoopFinderImpl { |
91 public: | 56 public: |
92 LoopFinderImpl(Graph* graph, LoopTree* loop_tree, Zone* zone) | 57 LoopFinderImpl(Graph* graph, LoopTree* loop_tree, Zone* zone) |
93 : end_(graph->end()), | 58 : zone_(zone), |
| 59 end_(graph->end()), |
94 queue_(zone), | 60 queue_(zone), |
95 queued_(graph, 2), | 61 queued_(graph, 2), |
96 info_(graph->NodeCount(), kEmptyNodeInfo, zone), | 62 info_(graph->NodeCount(), {nullptr, nullptr}, zone), |
97 loops_(zone), | 63 loops_(zone), |
| 64 loop_num_(graph->NodeCount(), -1, zone), |
98 loop_tree_(loop_tree), | 65 loop_tree_(loop_tree), |
99 loops_found_(0) {} | 66 loops_found_(0), |
| 67 width_(0), |
| 68 backward_(nullptr), |
| 69 forward_(nullptr) {} |
100 | 70 |
101 void Run() { | 71 void Run() { |
102 PropagateBackward(); | 72 PropagateBackward(); |
103 PropagateForward(); | 73 PropagateForward(); |
104 FinishLoopTree(); | 74 FinishLoopTree(); |
105 } | 75 } |
106 | 76 |
107 void Print() { | 77 void Print() { |
108 // Print out the results. | 78 // Print out the results. |
109 for (NodeInfo& ni : info_) { | 79 for (NodeInfo& ni : info_) { |
110 if (ni.node == nullptr) continue; | 80 if (ni.node == nullptr) continue; |
111 for (size_t i = 1; i <= loops_.size(); i++) { | 81 for (int i = 1; i <= loops_found_; i++) { |
112 if (ni.IsInLoop(i)) { | 82 int index = ni.node->id() * width_ + INDEX(i); |
| 83 bool marked_forward = forward_[index] & BIT(i); |
| 84 bool marked_backward = backward_[index] & BIT(i); |
| 85 if (marked_forward && marked_backward) { |
113 PrintF("X"); | 86 PrintF("X"); |
114 } else if (ni.forward & (1 << i)) { | 87 } else if (marked_forward) { |
115 PrintF("/"); | 88 PrintF("/"); |
116 } else if (ni.backward & (1 << i)) { | 89 } else if (marked_backward) { |
117 PrintF("\\"); | 90 PrintF("\\"); |
118 } else { | 91 } else { |
119 PrintF(" "); | 92 PrintF(" "); |
120 } | 93 } |
121 } | 94 } |
122 PrintF(" #%d:%s\n", ni.node->id(), ni.node->op()->mnemonic()); | 95 PrintF(" #%d:%s\n", ni.node->id(), ni.node->op()->mnemonic()); |
123 } | 96 } |
124 | 97 |
125 int i = 0; | 98 int i = 0; |
126 for (LoopInfo& li : loops_) { | 99 for (LoopInfo& li : loops_) { |
127 PrintF("Loop %d headed at #%d\n", i, li.header->id()); | 100 PrintF("Loop %d headed at #%d\n", i, li.header->id()); |
128 i++; | 101 i++; |
129 } | 102 } |
130 | 103 |
131 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { | 104 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { |
132 PrintLoop(loop); | 105 PrintLoop(loop); |
133 } | 106 } |
134 } | 107 } |
135 | 108 |
136 private: | 109 private: |
| 110 Zone* zone_; |
137 Node* end_; | 111 Node* end_; |
138 NodeDeque queue_; | 112 NodeDeque queue_; |
139 NodeMarker<bool> queued_; | 113 NodeMarker<bool> queued_; |
140 ZoneVector<NodeInfo> info_; | 114 ZoneVector<NodeInfo> info_; |
141 ZoneVector<LoopInfo> loops_; | 115 ZoneVector<LoopInfo> loops_; |
| 116 ZoneVector<int> loop_num_; |
142 LoopTree* loop_tree_; | 117 LoopTree* loop_tree_; |
143 size_t loops_found_; | 118 int loops_found_; |
| 119 int width_; |
| 120 uint32_t* backward_; |
| 121 uint32_t* forward_; |
| 122 |
| 123 int num_nodes() { |
| 124 return static_cast<int>(loop_tree_->node_to_loop_num_.size()); |
| 125 } |
| 126 |
| 127 // Tb = Tb | (Fb - loop_filter) |
| 128 bool PropagateBackwardMarks(Node* from, Node* to, int loop_filter) { |
| 129 if (from == to) return false; |
| 130 uint32_t* fp = &backward_[from->id() * width_]; |
| 131 uint32_t* tp = &backward_[to->id() * width_]; |
| 132 bool change = false; |
| 133 for (int i = 0; i < width_; i++) { |
| 134 uint32_t mask = i == INDEX(loop_filter) ? ~BIT(loop_filter) : 0xFFFFFFFF; |
| 135 uint32_t prev = tp[i]; |
| 136 uint32_t next = prev | (fp[i] & mask); |
| 137 tp[i] = next; |
| 138 if (!change && (prev != next)) change = true; |
| 139 } |
| 140 return change; |
| 141 } |
| 142 |
| 143 // Tb = Tb | B |
| 144 bool SetBackwardMark(Node* to, int loop_num) { |
| 145 uint32_t* tp = &backward_[to->id() * width_ + INDEX(loop_num)]; |
| 146 uint32_t prev = tp[0]; |
| 147 uint32_t next = prev | BIT(loop_num); |
| 148 tp[0] = next; |
| 149 return next != prev; |
| 150 } |
| 151 |
| 152 // Tf = Tf | B |
| 153 bool SetForwardMark(Node* to, int loop_num) { |
| 154 uint32_t* tp = &forward_[to->id() * width_ + INDEX(loop_num)]; |
| 155 uint32_t prev = tp[0]; |
| 156 uint32_t next = prev | BIT(loop_num); |
| 157 tp[0] = next; |
| 158 return next != prev; |
| 159 } |
| 160 |
| 161 // Tf = Tf | (Ff & Tb) |
| 162 bool PropagateForwardMarks(Node* from, Node* to) { |
| 163 if (from == to) return false; |
| 164 bool change = false; |
| 165 int findex = from->id() * width_; |
| 166 int tindex = to->id() * width_; |
| 167 for (int i = 0; i < width_; i++) { |
| 168 uint32_t marks = backward_[tindex + i] & forward_[findex + i]; |
| 169 uint32_t prev = forward_[tindex + i]; |
| 170 uint32_t next = prev | marks; |
| 171 forward_[tindex + i] = next; |
| 172 if (!change && (prev != next)) change = true; |
| 173 } |
| 174 return change; |
| 175 } |
| 176 |
| 177 bool IsInLoop(Node* node, int loop_num) { |
| 178 int offset = node->id() * width_ + INDEX(loop_num); |
| 179 return backward_[offset] & forward_[offset] & BIT(loop_num); |
| 180 } |
144 | 181 |
145 // Propagate marks backward from loop headers. | 182 // Propagate marks backward from loop headers. |
146 void PropagateBackward() { | 183 void PropagateBackward() { |
147 PropagateBackward(end_, kVisited); | 184 ResizeBackwardMarks(); |
| 185 SetBackwardMark(end_, 0); |
| 186 Queue(end_); |
148 | 187 |
149 while (!queue_.empty()) { | 188 while (!queue_.empty()) { |
150 Node* node = queue_.front(); | 189 Node* node = queue_.front(); |
| 190 info(node); |
151 queue_.pop_front(); | 191 queue_.pop_front(); |
152 queued_.Set(node, false); | 192 queued_.Set(node, false); |
153 | 193 |
| 194 int loop_num = -1; |
154 // Setup loop headers first. | 195 // Setup loop headers first. |
155 NodeInfo& ni = info(node); | |
156 if (node->opcode() == IrOpcode::kLoop) { | 196 if (node->opcode() == IrOpcode::kLoop) { |
157 // found the loop node first. | 197 // found the loop node first. |
158 CreateLoopInfo(node, ni); | 198 loop_num = CreateLoopInfo(node); |
159 } else if (node->opcode() == IrOpcode::kPhi || | 199 } else if (node->opcode() == IrOpcode::kPhi || |
160 node->opcode() == IrOpcode::kEffectPhi) { | 200 node->opcode() == IrOpcode::kEffectPhi) { |
161 // found a phi first. | 201 // found a phi first. |
162 Node* merge = node->InputAt(node->InputCount() - 1); | 202 Node* merge = node->InputAt(node->InputCount() - 1); |
163 if (merge->opcode() == IrOpcode::kLoop) { | 203 if (merge->opcode() == IrOpcode::kLoop) { |
164 NodeInfo& mi = info(merge); | 204 loop_num = CreateLoopInfo(merge); |
165 CreateLoopInfo(merge, mi); | |
166 ni.MarkBackward(mi.loop_mark); | |
167 } | 205 } |
168 } | 206 } |
169 | 207 |
170 // Propagate reachability marks backwards from this node. | 208 // Propagate marks backwards from this node. |
171 if (ni.IsLoopHeader()) { | 209 for (int i = 0; i < node->InputCount(); i++) { |
172 // Handle edges from loop header nodes specially. | 210 Node* input = node->InputAt(i); |
173 for (int i = 0; i < node->InputCount(); i++) { | 211 if (loop_num > 0 && i != kAssumedLoopEntryIndex) { |
174 if (i == kAssumedLoopEntryIndex) { | 212 // Only propagate the loop mark on backedges. |
175 // Don't propagate the loop mark backwards on the entry edge. | 213 if (SetBackwardMark(input, loop_num)) Queue(input); |
176 PropagateBackward(node->InputAt(0), | 214 } else { |
177 kVisited | (ni.backward & ~ni.loop_mark)); | 215 // Entry or normal edge. Propagate all marks except loop_num. |
178 } else { | 216 if (PropagateBackwardMarks(node, input, loop_num)) Queue(input); |
179 // Only propagate the loop mark on backedges. | |
180 PropagateBackward(node->InputAt(i), ni.loop_mark); | |
181 } | |
182 } | |
183 } else { | |
184 // Propagate all loop marks backwards for a normal node. | |
185 for (Node* const input : node->inputs()) { | |
186 PropagateBackward(input, ni.backward); | |
187 } | 217 } |
188 } | 218 } |
189 } | 219 } |
190 } | 220 } |
191 | 221 |
192 // Make a new loop header for the given node. | 222 // Make a new loop if necessary for the given node. |
193 void CreateLoopInfo(Node* node, NodeInfo& ni) { | 223 int CreateLoopInfo(Node* node) { |
194 if (ni.IsLoopHeader()) return; // loop already set up. | 224 int loop_num = LoopNum(node); |
| 225 if (loop_num > 0) return loop_num; |
195 | 226 |
196 loops_found_++; | 227 loop_num = ++loops_found_; |
197 size_t loop_num = loops_.size() + 1; | 228 if (INDEX(loop_num) >= width_) ResizeBackwardMarks(); |
198 CHECK(loops_found_ <= kMaxLoops); // TODO(titzer): don't crash. | 229 |
199 // Create a new loop. | 230 // Create a new loop. |
200 loops_.push_back({node, nullptr, nullptr, nullptr}); | 231 loops_.push_back({node, nullptr, nullptr, nullptr}); |
201 loop_tree_->NewLoop(); | 232 loop_tree_->NewLoop(); |
202 LoopMarks loop_mark = kVisited | (1 << loop_num); | 233 SetBackwardMark(node, loop_num); |
203 ni.loop_mark = loop_mark; | 234 loop_tree_->node_to_loop_num_[node->id()] = loop_num; |
204 | 235 |
205 // Setup loop mark for phis attached to loop header. | 236 // Setup loop mark for phis attached to loop header. |
206 for (Node* use : node->uses()) { | 237 for (Node* use : node->uses()) { |
207 if (use->opcode() == IrOpcode::kPhi || | 238 if (use->opcode() == IrOpcode::kPhi || |
208 use->opcode() == IrOpcode::kEffectPhi) { | 239 use->opcode() == IrOpcode::kEffectPhi) { |
209 info(use).loop_mark = loop_mark; | 240 SetBackwardMark(use, loop_num); |
| 241 loop_tree_->node_to_loop_num_[use->id()] = loop_num; |
210 } | 242 } |
211 } | 243 } |
| 244 |
| 245 return loop_num; |
| 246 } |
| 247 |
| 248 void ResizeBackwardMarks() { |
| 249 int new_width = width_ + 1; |
| 250 int max = num_nodes(); |
| 251 uint32_t* new_backward = zone_->NewArray<uint32_t>(new_width * max); |
| 252 memset(new_backward, 0, new_width * max * sizeof(uint32_t)); |
| 253 if (width_ > 0) { // copy old matrix data. |
| 254 for (int i = 0; i < max; i++) { |
| 255 uint32_t* np = &new_backward[i * new_width]; |
| 256 uint32_t* op = &backward_[i * width_]; |
| 257 for (int j = 0; j < width_; j++) np[j] = op[j]; |
| 258 } |
| 259 } |
| 260 width_ = new_width; |
| 261 backward_ = new_backward; |
| 262 } |
| 263 |
| 264 void ResizeForwardMarks() { |
| 265 int max = num_nodes(); |
| 266 forward_ = zone_->NewArray<uint32_t>(width_ * max); |
| 267 memset(forward_, 0, width_ * max * sizeof(uint32_t)); |
212 } | 268 } |
213 | 269 |
214 // Propagate marks forward from loops. | 270 // Propagate marks forward from loops. |
215 void PropagateForward() { | 271 void PropagateForward() { |
| 272 ResizeForwardMarks(); |
216 for (LoopInfo& li : loops_) { | 273 for (LoopInfo& li : loops_) { |
217 queued_.Set(li.header, true); | 274 SetForwardMark(li.header, LoopNum(li.header)); |
218 queue_.push_back(li.header); | 275 Queue(li.header); |
219 NodeInfo& ni = info(li.header); | |
220 ni.forward = ni.loop_mark; | |
221 } | 276 } |
222 // Propagate forward on paths that were backward reachable from backedges. | 277 // Propagate forward on paths that were backward reachable from backedges. |
223 while (!queue_.empty()) { | 278 while (!queue_.empty()) { |
224 Node* node = queue_.front(); | 279 Node* node = queue_.front(); |
225 queue_.pop_front(); | 280 queue_.pop_front(); |
226 queued_.Set(node, false); | 281 queued_.Set(node, false); |
227 NodeInfo& ni = info(node); | |
228 for (Edge edge : node->use_edges()) { | 282 for (Edge edge : node->use_edges()) { |
229 Node* use = edge.from(); | 283 Node* use = edge.from(); |
230 NodeInfo& ui = info(use); | 284 if (!IsBackedge(use, edge)) { |
231 if (IsBackedge(use, ui, edge)) continue; // skip backedges. | 285 if (PropagateForwardMarks(node, use)) Queue(use); |
232 LoopMarks both = ni.forward & ui.backward; | |
233 if (ui.MarkForward(both) && !queued_.Get(use)) { | |
234 queued_.Set(use, true); | |
235 queue_.push_back(use); | |
236 } | 286 } |
237 } | 287 } |
238 } | 288 } |
239 } | 289 } |
240 | 290 |
241 bool IsBackedge(Node* use, NodeInfo& ui, Edge& edge) { | 291 bool IsBackedge(Node* use, Edge& edge) { |
242 // TODO(titzer): checking for backedges here is ugly. | 292 if (LoopNum(use) <= 0) return false; |
243 if (!ui.IsLoopHeader()) return false; | |
244 if (edge.index() == kAssumedLoopEntryIndex) return false; | 293 if (edge.index() == kAssumedLoopEntryIndex) return false; |
245 if (use->opcode() == IrOpcode::kPhi || | 294 if (use->opcode() == IrOpcode::kPhi || |
246 use->opcode() == IrOpcode::kEffectPhi) { | 295 use->opcode() == IrOpcode::kEffectPhi) { |
247 return !NodeProperties::IsControlEdge(edge); | 296 return !NodeProperties::IsControlEdge(edge); |
248 } | 297 } |
249 return true; | 298 return true; |
250 } | 299 } |
251 | 300 |
| 301 int LoopNum(Node* node) { return loop_tree_->node_to_loop_num_[node->id()]; } |
| 302 |
252 NodeInfo& info(Node* node) { | 303 NodeInfo& info(Node* node) { |
253 NodeInfo& i = info_[node->id()]; | 304 NodeInfo& i = info_[node->id()]; |
254 if (i.node == nullptr) i.node = node; | 305 if (i.node == nullptr) i.node = node; |
255 return i; | 306 return i; |
256 } | 307 } |
257 | 308 |
258 void PropagateBackward(Node* node, LoopMarks marks) { | 309 void Queue(Node* node) { |
259 if (info(node).MarkBackward(marks) && !queued_.Get(node)) { | 310 if (!queued_.Get(node)) { |
260 queue_.push_back(node); | 311 queue_.push_back(node); |
261 queued_.Set(node, true); | 312 queued_.Set(node, true); |
262 } | 313 } |
263 } | 314 } |
264 | 315 |
265 void FinishLoopTree() { | 316 void FinishLoopTree() { |
| 317 DCHECK(loops_found_ == static_cast<int>(loops_.size())); |
| 318 DCHECK(loops_found_ == static_cast<int>(loop_tree_->all_loops_.size())); |
| 319 |
266 // Degenerate cases. | 320 // Degenerate cases. |
267 if (loops_.size() == 0) return; | 321 if (loops_found_ == 0) return; |
268 if (loops_.size() == 1) return FinishSingleLoop(); | 322 if (loops_found_ == 1) return FinishSingleLoop(); |
269 | 323 |
270 for (size_t i = 1; i <= loops_.size(); i++) ConnectLoopTree(i); | 324 for (int i = 1; i <= loops_found_; i++) ConnectLoopTree(i); |
271 | 325 |
272 size_t count = 0; | 326 size_t count = 0; |
273 // Place the node into the innermost nested loop of which it is a member. | 327 // Place the node into the innermost nested loop of which it is a member. |
274 for (NodeInfo& ni : info_) { | 328 for (NodeInfo& ni : info_) { |
275 if (ni.node == nullptr || !ni.IsInAnyLoop()) continue; | 329 if (ni.node == nullptr) continue; |
276 | 330 |
277 LoopInfo* innermost = nullptr; | 331 LoopInfo* innermost = nullptr; |
278 size_t index = 0; | 332 int innermost_index = 0; |
279 for (size_t i = 1; i <= loops_.size(); i++) { | 333 int pos = ni.node->id() * width_; |
280 if (ni.IsInLoop(i)) { | 334 // Search the marks word by word. |
281 LoopInfo* loop = &loops_[i - 1]; | 335 for (int i = 0; i < width_; i++) { |
282 if (innermost == nullptr || | 336 uint32_t marks = backward_[pos + i] & forward_[pos + i]; |
283 loop->loop->depth_ > innermost->loop->depth_) { | 337 for (int j = 0; j < 32; j++) { |
284 innermost = loop; | 338 if (marks & (1u << j)) { |
285 index = i; | 339 int loop_num = i * 32 + j; |
| 340 if (loop_num == 0) continue; |
| 341 LoopInfo* loop = &loops_[loop_num - 1]; |
| 342 if (innermost == nullptr || |
| 343 loop->loop->depth_ > innermost->loop->depth_) { |
| 344 innermost = loop; |
| 345 innermost_index = loop_num; |
| 346 } |
286 } | 347 } |
287 } | 348 } |
288 } | 349 } |
289 if (ni.IsInHeaderForLoop(index)) { | 350 if (innermost == nullptr) continue; |
| 351 if (LoopNum(ni.node) == innermost_index) { |
290 ni.next = innermost->header_list; | 352 ni.next = innermost->header_list; |
291 innermost->header_list = ∋ | 353 innermost->header_list = ∋ |
292 } else { | 354 } else { |
293 ni.next = innermost->body_list; | 355 ni.next = innermost->body_list; |
294 innermost->body_list = ∋ | 356 innermost->body_list = ∋ |
295 } | 357 } |
296 count++; | 358 count++; |
297 } | 359 } |
298 | 360 |
299 // Serialize the node lists for loops into the loop tree. | 361 // Serialize the node lists for loops into the loop tree. |
300 loop_tree_->loop_nodes_.reserve(count); | 362 loop_tree_->loop_nodes_.reserve(count); |
301 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { | 363 for (LoopTree::Loop* loop : loop_tree_->outer_loops_) { |
302 SerializeLoop(loop); | 364 SerializeLoop(loop); |
303 } | 365 } |
304 } | 366 } |
305 | 367 |
306 // Handle the simpler case of a single loop (no checks for nesting necessary). | 368 // Handle the simpler case of a single loop (no checks for nesting necessary). |
307 void FinishSingleLoop() { | 369 void FinishSingleLoop() { |
308 DCHECK(loops_.size() == 1); | |
309 DCHECK(loop_tree_->all_loops_.size() == 1); | |
310 | |
311 // Place nodes into the loop header and body. | 370 // Place nodes into the loop header and body. |
312 LoopInfo* li = &loops_[0]; | 371 LoopInfo* li = &loops_[0]; |
313 li->loop = &loop_tree_->all_loops_[0]; | 372 li->loop = &loop_tree_->all_loops_[0]; |
314 loop_tree_->SetParent(nullptr, li->loop); | 373 loop_tree_->SetParent(nullptr, li->loop); |
315 size_t count = 0; | 374 size_t count = 0; |
316 for (NodeInfo& ni : info_) { | 375 for (NodeInfo& ni : info_) { |
317 if (ni.node == nullptr || !ni.IsInAnyLoop()) continue; | 376 if (ni.node == nullptr || !IsInLoop(ni.node, 1)) continue; |
318 DCHECK(ni.IsInLoop(1)); | 377 if (LoopNum(ni.node) == 1) { |
319 if (ni.IsInHeaderForLoop(1)) { | |
320 ni.next = li->header_list; | 378 ni.next = li->header_list; |
321 li->header_list = ∋ | 379 li->header_list = ∋ |
322 } else { | 380 } else { |
323 ni.next = li->body_list; | 381 ni.next = li->body_list; |
324 li->body_list = ∋ | 382 li->body_list = ∋ |
325 } | 383 } |
326 count++; | 384 count++; |
327 } | 385 } |
328 | 386 |
329 // Serialize the node lists for the loop into the loop tree. | 387 // Serialize the node lists for the loop into the loop tree. |
330 loop_tree_->loop_nodes_.reserve(count); | 388 loop_tree_->loop_nodes_.reserve(count); |
331 SerializeLoop(li->loop); | 389 SerializeLoop(li->loop); |
332 } | 390 } |
333 | 391 |
334 // Recursively serialize the list of header nodes and body nodes | 392 // Recursively serialize the list of header nodes and body nodes |
335 // so that nested loops occupy nested intervals. | 393 // so that nested loops occupy nested intervals. |
336 void SerializeLoop(LoopTree::Loop* loop) { | 394 void SerializeLoop(LoopTree::Loop* loop) { |
337 size_t loop_num = loop_tree_->LoopNum(loop); | 395 int loop_num = loop_tree_->LoopNum(loop); |
338 LoopInfo& li = loops_[loop_num - 1]; | 396 LoopInfo& li = loops_[loop_num - 1]; |
339 | 397 |
340 // Serialize the header. | 398 // Serialize the header. |
341 loop->header_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); | 399 loop->header_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); |
342 for (NodeInfo* ni = li.header_list; ni != nullptr; ni = ni->next) { | 400 for (NodeInfo* ni = li.header_list; ni != nullptr; ni = ni->next) { |
343 loop_tree_->loop_nodes_.push_back(ni->node); | 401 loop_tree_->loop_nodes_.push_back(ni->node); |
344 // TODO(titzer): lift loop count restriction. | 402 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num; |
345 loop_tree_->node_to_loop_num_[ni->node->id()] = | |
346 static_cast<uint8_t>(loop_num); | |
347 } | 403 } |
348 | 404 |
349 // Serialize the body. | 405 // Serialize the body. |
350 loop->body_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); | 406 loop->body_start_ = static_cast<int>(loop_tree_->loop_nodes_.size()); |
351 for (NodeInfo* ni = li.body_list; ni != nullptr; ni = ni->next) { | 407 for (NodeInfo* ni = li.body_list; ni != nullptr; ni = ni->next) { |
352 loop_tree_->loop_nodes_.push_back(ni->node); | 408 loop_tree_->loop_nodes_.push_back(ni->node); |
353 // TODO(titzer): lift loop count restriction. | 409 loop_tree_->node_to_loop_num_[ni->node->id()] = loop_num; |
354 loop_tree_->node_to_loop_num_[ni->node->id()] = | |
355 static_cast<uint8_t>(loop_num); | |
356 } | 410 } |
357 | 411 |
358 // Serialize nested loops. | 412 // Serialize nested loops. |
359 for (LoopTree::Loop* child : loop->children_) SerializeLoop(child); | 413 for (LoopTree::Loop* child : loop->children_) SerializeLoop(child); |
360 | 414 |
361 loop->body_end_ = static_cast<int>(loop_tree_->loop_nodes_.size()); | 415 loop->body_end_ = static_cast<int>(loop_tree_->loop_nodes_.size()); |
362 } | 416 } |
363 | 417 |
364 // Connect the LoopTree loops to their parents recursively. | 418 // Connect the LoopTree loops to their parents recursively. |
365 LoopTree::Loop* ConnectLoopTree(size_t loop_num) { | 419 LoopTree::Loop* ConnectLoopTree(int loop_num) { |
366 LoopInfo& li = loops_[loop_num - 1]; | 420 LoopInfo& li = loops_[loop_num - 1]; |
367 if (li.loop != nullptr) return li.loop; | 421 if (li.loop != nullptr) return li.loop; |
368 | 422 |
369 NodeInfo& ni = info(li.header); | 423 NodeInfo& ni = info(li.header); |
370 LoopTree::Loop* parent = nullptr; | 424 LoopTree::Loop* parent = nullptr; |
371 for (size_t i = 1; i <= loops_.size(); i++) { | 425 for (int i = 1; i <= loops_found_; i++) { |
372 if (i == loop_num) continue; | 426 if (i == loop_num) continue; |
373 if (ni.IsInLoop(i)) { | 427 if (IsInLoop(ni.node, i)) { |
374 // recursively create potential parent loops first. | 428 // recursively create potential parent loops first. |
375 LoopTree::Loop* upper = ConnectLoopTree(i); | 429 LoopTree::Loop* upper = ConnectLoopTree(i); |
376 if (parent == nullptr || upper->depth_ > parent->depth_) { | 430 if (parent == nullptr || upper->depth_ > parent->depth_) { |
377 parent = upper; | 431 parent = upper; |
378 } | 432 } |
379 } | 433 } |
380 } | 434 } |
381 li.loop = &loop_tree_->all_loops_[loop_num - 1]; | 435 li.loop = &loop_tree_->all_loops_[loop_num - 1]; |
382 loop_tree_->SetParent(parent, li.loop); | 436 loop_tree_->SetParent(parent, li.loop); |
383 return li.loop; | 437 return li.loop; |
(...skipping 22 matching lines...) Expand all Loading... |
406 finder.Run(); | 460 finder.Run(); |
407 if (FLAG_trace_turbo_graph) { | 461 if (FLAG_trace_turbo_graph) { |
408 finder.Print(); | 462 finder.Print(); |
409 } | 463 } |
410 return loop_tree; | 464 return loop_tree; |
411 } | 465 } |
412 | 466 |
413 } // namespace compiler | 467 } // namespace compiler |
414 } // namespace internal | 468 } // namespace internal |
415 } // namespace v8 | 469 } // namespace v8 |
OLD | NEW |