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-flow-optimizer.h" | |
6 | |
7 #include "src/compiler/js-graph.h" | |
8 #include "src/compiler/node-matchers.h" | |
9 #include "src/compiler/node-properties.h" | |
10 | |
11 namespace v8 { | |
12 namespace internal { | |
13 namespace compiler { | |
14 | |
15 ControlFlowOptimizer::ControlFlowOptimizer(JSGraph* jsgraph, Zone* zone) | |
16 : jsgraph_(jsgraph), | |
17 queue_(zone), | |
18 queued_(jsgraph->graph(), 2), | |
19 zone_(zone) {} | |
20 | |
21 | |
22 void ControlFlowOptimizer::Optimize() { | |
23 Enqueue(graph()->start()); | |
24 while (!queue_.empty()) { | |
25 Node* node = queue_.front(); | |
26 queue_.pop(); | |
27 if (node->IsDead()) continue; | |
28 switch (node->opcode()) { | |
29 case IrOpcode::kBranch: | |
30 VisitBranch(node); | |
31 break; | |
32 default: | |
33 VisitNode(node); | |
34 break; | |
35 } | |
36 } | |
37 } | |
38 | |
39 | |
40 void ControlFlowOptimizer::Enqueue(Node* node) { | |
41 DCHECK_NOT_NULL(node); | |
42 if (node->IsDead() || queued_.Get(node)) return; | |
43 queued_.Set(node, true); | |
44 queue_.push(node); | |
45 } | |
46 | |
47 | |
48 void ControlFlowOptimizer::VisitNode(Node* node) { | |
49 for (Node* use : node->uses()) { | |
50 if (NodeProperties::IsControl(use)) Enqueue(use); | |
51 } | |
52 } | |
53 | |
54 | |
55 void ControlFlowOptimizer::VisitBranch(Node* node) { | |
56 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | |
57 | |
58 Node* branch = node; | |
59 Node* cond = NodeProperties::GetValueInput(branch, 0); | |
60 if (cond->opcode() != IrOpcode::kWord32Equal) return VisitNode(node); | |
61 Int32BinopMatcher m(cond); | |
62 Node* index = m.left().node(); | |
63 if (!m.right().HasValue()) return VisitNode(node); | |
64 int32_t value = m.right().Value(); | |
65 ZoneSet<int32_t> values(zone()); | |
66 values.insert(value); | |
67 | |
68 Node* if_false; | |
69 Node* if_true; | |
70 while (true) { | |
71 auto it = branch->uses().begin(); | |
72 DCHECK(it != branch->uses().end()); | |
73 if_true = *it++; | |
74 DCHECK(it != branch->uses().end()); | |
75 if_false = *it++; | |
76 DCHECK(it == branch->uses().end()); | |
77 if (if_true->opcode() != IrOpcode::kIfTrue) std::swap(if_true, if_false); | |
Michael Starzinger
2015/02/17 12:23:35
At some point I think we want to move CollectSucce
Benedikt Meurer
2015/02/17 12:30:38
Done.
| |
78 DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode()); | |
79 DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode()); | |
80 | |
81 it = if_false->uses().begin(); | |
82 if (it == if_false->uses().end()) break; | |
83 Node* branch1 = *it++; | |
84 if (branch1->opcode() != IrOpcode::kBranch) break; | |
85 if (it != if_false->uses().end()) break; | |
86 Node* cond1 = branch1->InputAt(0); | |
87 if (cond1->opcode() != IrOpcode::kWord32Equal) break; | |
88 Int32BinopMatcher m1(cond1); | |
89 if (m1.left().node() != index) break; | |
90 if (!m1.right().HasValue()) break; | |
91 int32_t value1 = m1.right().Value(); | |
92 if (values.find(value1) != values.end()) break; | |
93 DCHECK_NE(value, value1); | |
94 | |
95 if (branch != node) { | |
96 branch->RemoveAllInputs(); | |
97 if_true->ReplaceInput(0, node); | |
98 } | |
99 if_true->set_op(common()->IfValue(value)); | |
100 if_false->RemoveAllInputs(); | |
101 Enqueue(if_true); | |
102 | |
103 branch = branch1; | |
104 value = value1; | |
105 values.insert(value); | |
106 } | |
107 | |
108 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | |
109 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); | |
110 DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode()); | |
111 DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode()); | |
112 if (branch == node) { | |
113 DCHECK_EQ(1u, values.size()); | |
114 Enqueue(if_true); | |
115 Enqueue(if_false); | |
116 } else { | |
117 DCHECK_LT(1u, values.size()); | |
118 node->set_op(common()->Switch(values.size() + 1)); | |
119 node->ReplaceInput(0, index); | |
120 if_true->set_op(common()->IfValue(value)); | |
121 if_true->ReplaceInput(0, node); | |
122 Enqueue(if_true); | |
123 if_false->set_op(common()->IfDefault()); | |
124 if_false->ReplaceInput(0, node); | |
125 Enqueue(if_false); | |
126 branch->RemoveAllInputs(); | |
127 } | |
128 } | |
129 | |
130 | |
131 CommonOperatorBuilder* ControlFlowOptimizer::common() const { | |
132 return jsgraph()->common(); | |
133 } | |
134 | |
135 | |
136 Graph* ControlFlowOptimizer::graph() const { return jsgraph()->graph(); } | |
137 | |
138 | |
139 MachineOperatorBuilder* ControlFlowOptimizer::machine() const { | |
140 return jsgraph()->machine(); | |
141 } | |
142 | |
143 } // namespace compiler | |
144 } // namespace internal | |
145 } // namespace v8 | |
OLD | NEW |