OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #ifndef V8_COMPILER_CONTROL_EQUIVALENCE_H_ | 5 #ifndef V8_COMPILER_CONTROL_EQUIVALENCE_H_ |
6 #define V8_COMPILER_CONTROL_EQUIVALENCE_H_ | 6 #define V8_COMPILER_CONTROL_EQUIVALENCE_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 Node* parent_node; // Parent node of entry during DFS walk. | 80 Node* parent_node; // Parent node of entry during DFS walk. |
81 Node* node; // Node that this stack entry belongs to. | 81 Node* node; // Node that this stack entry belongs to. |
82 }; | 82 }; |
83 | 83 |
84 // The stack is used during the undirected DFS walk. | 84 // The stack is used during the undirected DFS walk. |
85 typedef ZoneStack<DFSStackEntry> DFSStack; | 85 typedef ZoneStack<DFSStackEntry> DFSStack; |
86 | 86 |
87 struct NodeData { | 87 struct NodeData { |
88 size_t class_number; // Equivalence class number assigned to node. | 88 size_t class_number; // Equivalence class number assigned to node. |
89 size_t dfs_number; // Pre-order DFS number assigned to node. | 89 size_t dfs_number; // Pre-order DFS number assigned to node. |
| 90 bool visited; // Indicates node has already been visited. |
90 bool on_stack; // Indicates node is on DFS stack during walk. | 91 bool on_stack; // Indicates node is on DFS stack during walk. |
91 bool participates; // Indicates node participates in DFS walk. | 92 bool participates; // Indicates node participates in DFS walk. |
92 BracketList blist; // List of brackets per node. | 93 BracketList blist; // List of brackets per node. |
93 }; | 94 }; |
94 | 95 |
95 // The per-node data computed during the DFS walk. | 96 // The per-node data computed during the DFS walk. |
96 typedef ZoneVector<NodeData> Data; | 97 typedef ZoneVector<NodeData> Data; |
97 | 98 |
98 // Called at pre-visit during DFS walk. | 99 // Called at pre-visit during DFS walk. |
99 void VisitPre(Node* node) { | 100 void VisitPre(Node* node) { |
100 Trace("CEQ: Pre-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); | 101 Trace("CEQ: Pre-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); |
101 | 102 |
102 // Dispense a new pre-order number. | 103 // Dispense a new pre-order number. |
103 SetNumber(node, NewDFSNumber()); | 104 SetNumber(node, NewDFSNumber()); |
104 Trace(" Assigned DFS number is %d\n", GetNumber(node)); | 105 Trace(" Assigned DFS number is %d\n", GetNumber(node)); |
105 } | 106 } |
106 | 107 |
107 // Called at mid-visit during DFS walk. | 108 // Called at mid-visit during DFS walk. |
108 void VisitMid(Node* node, DFSDirection direction) { | 109 void VisitMid(Node* node, DFSDirection direction) { |
109 Trace("CEQ: Mid-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); | 110 Trace("CEQ: Mid-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); |
110 BracketList& blist = GetBracketList(node); | 111 BracketList& blist = GetBracketList(node); |
111 | 112 |
112 // Remove brackets pointing to this node [line:19]. | 113 // Remove brackets pointing to this node [line:19]. |
113 BracketListDelete(blist, node, direction); | 114 BracketListDelete(blist, node, direction); |
114 | 115 |
115 // Potentially introduce artificial dependency from start to end. | 116 // Potentially introduce artificial dependency from start to end. |
116 if (blist.empty()) { | 117 if (blist.empty()) { |
117 DCHECK_EQ(graph_->start(), node); | |
118 DCHECK_EQ(kInputDirection, direction); | 118 DCHECK_EQ(kInputDirection, direction); |
119 VisitBackedge(graph_->start(), graph_->end(), kInputDirection); | 119 VisitBackedge(node, graph_->end(), kInputDirection); |
120 } | 120 } |
121 | 121 |
122 // Potentially start a new equivalence class [line:37]. | 122 // Potentially start a new equivalence class [line:37]. |
123 BracketListTrace(blist); | 123 BracketListTrace(blist); |
124 Bracket* recent = &blist.back(); | 124 Bracket* recent = &blist.back(); |
125 if (recent->recent_size != blist.size()) { | 125 if (recent->recent_size != blist.size()) { |
126 recent->recent_size = blist.size(); | 126 recent->recent_size = blist.size(); |
127 recent->recent_class = NewClassNumber(); | 127 recent->recent_class = NewClassNumber(); |
128 } | 128 } |
129 | 129 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 | 182 |
183 if (entry.direction == kInputDirection) { | 183 if (entry.direction == kInputDirection) { |
184 if (entry.input != node->input_edges().end()) { | 184 if (entry.input != node->input_edges().end()) { |
185 Edge edge = *entry.input; | 185 Edge edge = *entry.input; |
186 Node* input = edge.to(); | 186 Node* input = edge.to(); |
187 ++(entry.input); | 187 ++(entry.input); |
188 if (NodeProperties::IsControlEdge(edge) && | 188 if (NodeProperties::IsControlEdge(edge) && |
189 NodeProperties::IsControl(input)) { | 189 NodeProperties::IsControl(input)) { |
190 // Visit next control input. | 190 // Visit next control input. |
191 if (!GetData(input)->participates) continue; | 191 if (!GetData(input)->participates) continue; |
| 192 if (GetData(input)->visited) continue; |
192 if (GetData(input)->on_stack) { | 193 if (GetData(input)->on_stack) { |
193 // Found backedge if input is on stack. | 194 // Found backedge if input is on stack. |
194 if (input != entry.parent_node) { | 195 if (input != entry.parent_node) { |
195 VisitBackedge(node, input, kInputDirection); | 196 VisitBackedge(node, input, kInputDirection); |
196 } | 197 } |
197 } else { | 198 } else { |
198 // Push input onto stack. | 199 // Push input onto stack. |
199 DFSPush(stack, input, node, kInputDirection); | 200 DFSPush(stack, input, node, kInputDirection); |
200 VisitPre(input); | 201 VisitPre(input); |
201 } | 202 } |
(...skipping 10 matching lines...) Expand all Loading... |
212 | 213 |
213 if (entry.direction == kUseDirection) { | 214 if (entry.direction == kUseDirection) { |
214 if (entry.use != node->use_edges().end()) { | 215 if (entry.use != node->use_edges().end()) { |
215 Edge edge = *entry.use; | 216 Edge edge = *entry.use; |
216 Node* use = edge.from(); | 217 Node* use = edge.from(); |
217 ++(entry.use); | 218 ++(entry.use); |
218 if (NodeProperties::IsControlEdge(edge) && | 219 if (NodeProperties::IsControlEdge(edge) && |
219 NodeProperties::IsControl(use)) { | 220 NodeProperties::IsControl(use)) { |
220 // Visit next control use. | 221 // Visit next control use. |
221 if (!GetData(use)->participates) continue; | 222 if (!GetData(use)->participates) continue; |
| 223 if (GetData(use)->visited) continue; |
222 if (GetData(use)->on_stack) { | 224 if (GetData(use)->on_stack) { |
223 // Found backedge if use is on stack. | 225 // Found backedge if use is on stack. |
224 if (use != entry.parent_node) { | 226 if (use != entry.parent_node) { |
225 VisitBackedge(node, use, kUseDirection); | 227 VisitBackedge(node, use, kUseDirection); |
226 } | 228 } |
227 } else { | 229 } else { |
228 // Push use onto stack. | 230 // Push use onto stack. |
229 DFSPush(stack, use, node, kUseDirection); | 231 DFSPush(stack, use, node, kUseDirection); |
230 VisitPre(use); | 232 VisitPre(use); |
231 } | 233 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 270 } |
269 } | 271 } |
270 | 272 |
271 private: | 273 private: |
272 NodeData* GetData(Node* node) { return &node_data_[node->id()]; } | 274 NodeData* GetData(Node* node) { return &node_data_[node->id()]; } |
273 int NewClassNumber() { return class_number_++; } | 275 int NewClassNumber() { return class_number_++; } |
274 int NewDFSNumber() { return dfs_number_++; } | 276 int NewDFSNumber() { return dfs_number_++; } |
275 | 277 |
276 // Template used to initialize per-node data. | 278 // Template used to initialize per-node data. |
277 NodeData EmptyData() { | 279 NodeData EmptyData() { |
278 return {kInvalidClass, 0, false, false, BracketList(zone_)}; | 280 return {kInvalidClass, 0, false, false, false, BracketList(zone_)}; |
279 } | 281 } |
280 | 282 |
281 // Accessors for the DFS number stored within the per-node data. | 283 // Accessors for the DFS number stored within the per-node data. |
282 size_t GetNumber(Node* node) { return GetData(node)->dfs_number; } | 284 size_t GetNumber(Node* node) { return GetData(node)->dfs_number; } |
283 void SetNumber(Node* node, size_t number) { | 285 void SetNumber(Node* node, size_t number) { |
284 GetData(node)->dfs_number = number; | 286 GetData(node)->dfs_number = number; |
285 } | 287 } |
286 | 288 |
287 // Accessors for the equivalence class stored within the per-node data. | 289 // Accessors for the equivalence class stored within the per-node data. |
288 size_t GetClass(Node* node) { return GetData(node)->class_number; } | 290 size_t GetClass(Node* node) { return GetData(node)->class_number; } |
289 void SetClass(Node* node, size_t number) { | 291 void SetClass(Node* node, size_t number) { |
290 GetData(node)->class_number = number; | 292 GetData(node)->class_number = number; |
291 } | 293 } |
292 | 294 |
293 // Accessors for the bracket list stored within the per-node data. | 295 // Accessors for the bracket list stored within the per-node data. |
294 BracketList& GetBracketList(Node* node) { return GetData(node)->blist; } | 296 BracketList& GetBracketList(Node* node) { return GetData(node)->blist; } |
295 void SetBracketList(Node* node, BracketList& list) { | 297 void SetBracketList(Node* node, BracketList& list) { |
296 GetData(node)->blist = list; | 298 GetData(node)->blist = list; |
297 } | 299 } |
298 | 300 |
299 // Mutates the DFS stack by pushing an entry. | 301 // Mutates the DFS stack by pushing an entry. |
300 void DFSPush(DFSStack& stack, Node* node, Node* from, DFSDirection dir) { | 302 void DFSPush(DFSStack& stack, Node* node, Node* from, DFSDirection dir) { |
301 DCHECK(GetData(node)->participates); | 303 DCHECK(GetData(node)->participates); |
| 304 DCHECK(!GetData(node)->visited); |
302 GetData(node)->on_stack = true; | 305 GetData(node)->on_stack = true; |
303 Node::InputEdges::iterator input = node->input_edges().begin(); | 306 Node::InputEdges::iterator input = node->input_edges().begin(); |
304 Node::UseEdges::iterator use = node->use_edges().begin(); | 307 Node::UseEdges::iterator use = node->use_edges().begin(); |
305 stack.push({dir, input, use, from, node}); | 308 stack.push({dir, input, use, from, node}); |
306 } | 309 } |
307 | 310 |
308 // Mutates the DFS stack by popping an entry. | 311 // Mutates the DFS stack by popping an entry. |
309 void DFSPop(DFSStack& stack, Node* node) { | 312 void DFSPop(DFSStack& stack, Node* node) { |
310 DCHECK_EQ(stack.top().node, node); | 313 DCHECK_EQ(stack.top().node, node); |
311 GetData(node)->on_stack = false; | 314 GetData(node)->on_stack = false; |
312 GetData(node)->participates = false; | 315 GetData(node)->visited = true; |
313 stack.pop(); | 316 stack.pop(); |
314 } | 317 } |
315 | 318 |
316 // TODO(mstarzinger): Optimize this to avoid linear search. | 319 // TODO(mstarzinger): Optimize this to avoid linear search. |
317 void BracketListDelete(BracketList& blist, Node* to, DFSDirection direction) { | 320 void BracketListDelete(BracketList& blist, Node* to, DFSDirection direction) { |
318 for (BracketList::iterator i = blist.begin(); i != blist.end(); /*nop*/) { | 321 for (BracketList::iterator i = blist.begin(); i != blist.end(); /*nop*/) { |
319 if (i->to == to && i->direction != direction) { | 322 if (i->to == to && i->direction != direction) { |
320 Trace(" BList erased: {%d->%d}\n", i->from->id(), i->to->id()); | 323 Trace(" BList erased: {%d->%d}\n", i->from->id(), i->to->id()); |
321 i = blist.erase(i); | 324 i = blist.erase(i); |
322 } else { | 325 } else { |
(...skipping 26 matching lines...) Expand all Loading... |
349 int dfs_number_; // Generates new DFS pre-order numbers on demand. | 352 int dfs_number_; // Generates new DFS pre-order numbers on demand. |
350 int class_number_; // Generates new equivalence class numbers on demand. | 353 int class_number_; // Generates new equivalence class numbers on demand. |
351 Data node_data_; // Per-node data stored as a side-table. | 354 Data node_data_; // Per-node data stored as a side-table. |
352 }; | 355 }; |
353 | 356 |
354 } // namespace compiler | 357 } // namespace compiler |
355 } // namespace internal | 358 } // namespace internal |
356 } // namespace v8 | 359 } // namespace v8 |
357 | 360 |
358 #endif // V8_COMPILER_CONTROL_EQUIVALENCE_H_ | 361 #endif // V8_COMPILER_CONTROL_EQUIVALENCE_H_ |
OLD | NEW |