| 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 |