| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 the V8 project authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "src/compiler/control-equivalence.h" | 
|  | 6 #include "src/compiler/node-properties.h" | 
|  | 7 | 
|  | 8 #define TRACE(...)                                 \ | 
|  | 9   do {                                             \ | 
|  | 10     if (FLAG_trace_turbo_ceq) PrintF(__VA_ARGS__); \ | 
|  | 11   } while (false) | 
|  | 12 | 
|  | 13 namespace v8 { | 
|  | 14 namespace internal { | 
|  | 15 namespace compiler { | 
|  | 16 | 
|  | 17 void ControlEquivalence::Run(Node* exit) { | 
|  | 18   if (GetClass(exit) == kInvalidClass) { | 
|  | 19     DetermineParticipation(exit); | 
|  | 20     RunUndirectedDFS(exit); | 
|  | 21   } | 
|  | 22 } | 
|  | 23 | 
|  | 24 | 
|  | 25 // static | 
|  | 26 STATIC_CONST_MEMBER_DEFINITION const size_t ControlEquivalence::kInvalidClass; | 
|  | 27 | 
|  | 28 | 
|  | 29 void ControlEquivalence::VisitPre(Node* node) { | 
|  | 30   TRACE("CEQ: Pre-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); | 
|  | 31 | 
|  | 32   // Dispense a new pre-order number. | 
|  | 33   SetNumber(node, NewDFSNumber()); | 
|  | 34   TRACE("  Assigned DFS number is %zu\n", GetNumber(node)); | 
|  | 35 } | 
|  | 36 | 
|  | 37 | 
|  | 38 void ControlEquivalence::VisitMid(Node* node, DFSDirection direction) { | 
|  | 39   TRACE("CEQ: Mid-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); | 
|  | 40   BracketList& blist = GetBracketList(node); | 
|  | 41 | 
|  | 42   // Remove brackets pointing to this node [line:19]. | 
|  | 43   BracketListDelete(blist, node, direction); | 
|  | 44 | 
|  | 45   // Potentially introduce artificial dependency from start to end. | 
|  | 46   if (blist.empty()) { | 
|  | 47     DCHECK_EQ(kInputDirection, direction); | 
|  | 48     VisitBackedge(node, graph_->end(), kInputDirection); | 
|  | 49   } | 
|  | 50 | 
|  | 51   // Potentially start a new equivalence class [line:37]. | 
|  | 52   BracketListTRACE(blist); | 
|  | 53   Bracket* recent = &blist.back(); | 
|  | 54   if (recent->recent_size != blist.size()) { | 
|  | 55     recent->recent_size = blist.size(); | 
|  | 56     recent->recent_class = NewClassNumber(); | 
|  | 57   } | 
|  | 58 | 
|  | 59   // Assign equivalence class to node. | 
|  | 60   SetClass(node, recent->recent_class); | 
|  | 61   TRACE("  Assigned class number is %zu\n", GetClass(node)); | 
|  | 62 } | 
|  | 63 | 
|  | 64 | 
|  | 65 void ControlEquivalence::VisitPost(Node* node, Node* parent_node, | 
|  | 66                                    DFSDirection direction) { | 
|  | 67   TRACE("CEQ: Post-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); | 
|  | 68   BracketList& blist = GetBracketList(node); | 
|  | 69 | 
|  | 70   // Remove brackets pointing to this node [line:19]. | 
|  | 71   BracketListDelete(blist, node, direction); | 
|  | 72 | 
|  | 73   // Propagate bracket list up the DFS tree [line:13]. | 
|  | 74   if (parent_node != NULL) { | 
|  | 75     BracketList& parent_blist = GetBracketList(parent_node); | 
|  | 76     parent_blist.splice(parent_blist.end(), blist); | 
|  | 77   } | 
|  | 78 } | 
|  | 79 | 
|  | 80 | 
|  | 81 void ControlEquivalence::VisitBackedge(Node* from, Node* to, | 
|  | 82                                        DFSDirection direction) { | 
|  | 83   TRACE("CEQ: Backedge from #%d:%s to #%d:%s\n", from->id(), | 
|  | 84         from->op()->mnemonic(), to->id(), to->op()->mnemonic()); | 
|  | 85 | 
|  | 86   // Push backedge onto the bracket list [line:25]. | 
|  | 87   Bracket bracket = {direction, kInvalidClass, 0, from, to}; | 
|  | 88   GetBracketList(from).push_back(bracket); | 
|  | 89 } | 
|  | 90 | 
|  | 91 | 
|  | 92 void ControlEquivalence::RunUndirectedDFS(Node* exit) { | 
|  | 93   ZoneStack<DFSStackEntry> stack(zone_); | 
|  | 94   DFSPush(stack, exit, NULL, kInputDirection); | 
|  | 95   VisitPre(exit); | 
|  | 96 | 
|  | 97   while (!stack.empty()) {  // Undirected depth-first backwards traversal. | 
|  | 98     DFSStackEntry& entry = stack.top(); | 
|  | 99     Node* node = entry.node; | 
|  | 100 | 
|  | 101     if (entry.direction == kInputDirection) { | 
|  | 102       if (entry.input != node->input_edges().end()) { | 
|  | 103         Edge edge = *entry.input; | 
|  | 104         Node* input = edge.to(); | 
|  | 105         ++(entry.input); | 
|  | 106         if (NodeProperties::IsControlEdge(edge)) { | 
|  | 107           // Visit next control input. | 
|  | 108           if (!GetData(input)->participates) continue; | 
|  | 109           if (GetData(input)->visited) continue; | 
|  | 110           if (GetData(input)->on_stack) { | 
|  | 111             // Found backedge if input is on stack. | 
|  | 112             if (input != entry.parent_node) { | 
|  | 113               VisitBackedge(node, input, kInputDirection); | 
|  | 114             } | 
|  | 115           } else { | 
|  | 116             // Push input onto stack. | 
|  | 117             DFSPush(stack, input, node, kInputDirection); | 
|  | 118             VisitPre(input); | 
|  | 119           } | 
|  | 120         } | 
|  | 121         continue; | 
|  | 122       } | 
|  | 123       if (entry.use != node->use_edges().end()) { | 
|  | 124         // Switch direction to uses. | 
|  | 125         entry.direction = kUseDirection; | 
|  | 126         VisitMid(node, kInputDirection); | 
|  | 127         continue; | 
|  | 128       } | 
|  | 129     } | 
|  | 130 | 
|  | 131     if (entry.direction == kUseDirection) { | 
|  | 132       if (entry.use != node->use_edges().end()) { | 
|  | 133         Edge edge = *entry.use; | 
|  | 134         Node* use = edge.from(); | 
|  | 135         ++(entry.use); | 
|  | 136         if (NodeProperties::IsControlEdge(edge)) { | 
|  | 137           // Visit next control use. | 
|  | 138           if (!GetData(use)->participates) continue; | 
|  | 139           if (GetData(use)->visited) continue; | 
|  | 140           if (GetData(use)->on_stack) { | 
|  | 141             // Found backedge if use is on stack. | 
|  | 142             if (use != entry.parent_node) { | 
|  | 143               VisitBackedge(node, use, kUseDirection); | 
|  | 144             } | 
|  | 145           } else { | 
|  | 146             // Push use onto stack. | 
|  | 147             DFSPush(stack, use, node, kUseDirection); | 
|  | 148             VisitPre(use); | 
|  | 149           } | 
|  | 150         } | 
|  | 151         continue; | 
|  | 152       } | 
|  | 153       if (entry.input != node->input_edges().end()) { | 
|  | 154         // Switch direction to inputs. | 
|  | 155         entry.direction = kInputDirection; | 
|  | 156         VisitMid(node, kUseDirection); | 
|  | 157         continue; | 
|  | 158       } | 
|  | 159     } | 
|  | 160 | 
|  | 161     // Pop node from stack when done with all inputs and uses. | 
|  | 162     DCHECK(entry.input == node->input_edges().end()); | 
|  | 163     DCHECK(entry.use == node->use_edges().end()); | 
|  | 164     DFSPop(stack, node); | 
|  | 165     VisitPost(node, entry.parent_node, entry.direction); | 
|  | 166   } | 
|  | 167 } | 
|  | 168 | 
|  | 169 void ControlEquivalence::DetermineParticipationEnqueue(ZoneQueue<Node*>& queue, | 
|  | 170                                                        Node* node) { | 
|  | 171   if (!GetData(node)->participates) { | 
|  | 172     GetData(node)->participates = true; | 
|  | 173     queue.push(node); | 
|  | 174   } | 
|  | 175 } | 
|  | 176 | 
|  | 177 | 
|  | 178 void ControlEquivalence::DetermineParticipation(Node* exit) { | 
|  | 179   ZoneQueue<Node*> queue(zone_); | 
|  | 180   DetermineParticipationEnqueue(queue, exit); | 
|  | 181   while (!queue.empty()) {  // Breadth-first backwards traversal. | 
|  | 182     Node* node = queue.front(); | 
|  | 183     queue.pop(); | 
|  | 184     int max = NodeProperties::PastControlIndex(node); | 
|  | 185     for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) { | 
|  | 186       DetermineParticipationEnqueue(queue, node->InputAt(i)); | 
|  | 187     } | 
|  | 188   } | 
|  | 189 } | 
|  | 190 | 
|  | 191 | 
|  | 192 void ControlEquivalence::DFSPush(DFSStack& stack, Node* node, Node* from, | 
|  | 193                                  DFSDirection dir) { | 
|  | 194   DCHECK(GetData(node)->participates); | 
|  | 195   DCHECK(!GetData(node)->visited); | 
|  | 196   GetData(node)->on_stack = true; | 
|  | 197   Node::InputEdges::iterator input = node->input_edges().begin(); | 
|  | 198   Node::UseEdges::iterator use = node->use_edges().begin(); | 
|  | 199   stack.push({dir, input, use, from, node}); | 
|  | 200 } | 
|  | 201 | 
|  | 202 | 
|  | 203 void ControlEquivalence::DFSPop(DFSStack& stack, Node* node) { | 
|  | 204   DCHECK_EQ(stack.top().node, node); | 
|  | 205   GetData(node)->on_stack = false; | 
|  | 206   GetData(node)->visited = true; | 
|  | 207   stack.pop(); | 
|  | 208 } | 
|  | 209 | 
|  | 210 | 
|  | 211 void ControlEquivalence::BracketListDelete(BracketList& blist, Node* to, | 
|  | 212                                            DFSDirection direction) { | 
|  | 213   // TODO(mstarzinger): Optimize this to avoid linear search. | 
|  | 214   for (BracketList::iterator i = blist.begin(); i != blist.end(); /*nop*/) { | 
|  | 215     if (i->to == to && i->direction != direction) { | 
|  | 216       TRACE("  BList erased: {%d->%d}\n", i->from->id(), i->to->id()); | 
|  | 217       i = blist.erase(i); | 
|  | 218     } else { | 
|  | 219       ++i; | 
|  | 220     } | 
|  | 221   } | 
|  | 222 } | 
|  | 223 | 
|  | 224 | 
|  | 225 void ControlEquivalence::BracketListTRACE(BracketList& blist) { | 
|  | 226   if (FLAG_trace_turbo_ceq) { | 
|  | 227     TRACE("  BList: "); | 
|  | 228     for (Bracket bracket : blist) { | 
|  | 229       TRACE("{%d->%d} ", bracket.from->id(), bracket.to->id()); | 
|  | 230     } | 
|  | 231     TRACE("\n"); | 
|  | 232   } | 
|  | 233 } | 
|  | 234 | 
|  | 235 }  // namespace compiler | 
|  | 236 }  // namespace internal | 
|  | 237 }  // namespace v8 | 
| OLD | NEW | 
|---|