Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(308)

Side by Side Diff: src/compiler/control-flow-optimizer.cc

Issue 1054963002: [turbofan] Introduce BranchMatcher and DiamondMatcher helpers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/common-operator-reducer.cc ('k') | src/compiler/control-reducer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 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/control-flow-optimizer.h" 5 #include "src/compiler/control-flow-optimizer.h"
6 6
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 10
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 116
117 Node* branch = node; 117 Node* branch = node;
118 Node* cond = NodeProperties::GetValueInput(branch, 0); 118 Node* cond = NodeProperties::GetValueInput(branch, 0);
119 if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return false; 119 if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return false;
120 Node* merge = NodeProperties::GetControlInput(branch); 120 Node* merge = NodeProperties::GetControlInput(branch);
121 if (merge->opcode() != IrOpcode::kMerge || 121 if (merge->opcode() != IrOpcode::kMerge ||
122 NodeProperties::GetControlInput(cond) != merge) { 122 NodeProperties::GetControlInput(cond) != merge) {
123 return false; 123 return false;
124 } 124 }
125 // Grab the IfTrue/IfFalse projections of the Branch. 125 // Grab the IfTrue/IfFalse projections of the Branch.
126 Node* control_projections[2]; 126 BranchMatcher matcher(branch);
127 NodeProperties::CollectControlProjections(branch, control_projections,
128 arraysize(control_projections));
129 Node* if_true = control_projections[0];
130 Node* if_false = control_projections[1];
131 DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode());
132 DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
133 // Check/collect other Phi/EffectPhi nodes hanging off the Merge. 127 // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
134 NodeVector phis(zone()); 128 NodeVector phis(zone());
135 for (Node* const use : merge->uses()) { 129 for (Node* const use : merge->uses()) {
136 if (use == branch || use == cond) continue; 130 if (use == branch || use == cond) continue;
137 // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the 131 // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the
138 // Merge. Ideally, we would just clone the nodes (and everything that 132 // Merge. Ideally, we would just clone the nodes (and everything that
139 // depends on it to some distant join point), but that requires knowledge 133 // depends on it to some distant join point), but that requires knowledge
140 // about dominance/post-dominance. 134 // about dominance/post-dominance.
141 if (!NodeProperties::IsPhi(use)) return false; 135 if (!NodeProperties::IsPhi(use)) return false;
142 for (Edge edge : use->use_edges()) { 136 for (Edge edge : use->use_edges()) {
143 // Right now we can only handle Phi/EffectPhi nodes whose uses are 137 // Right now we can only handle Phi/EffectPhi nodes whose uses are
144 // directly control-dependend on either the IfTrue or the IfFalse 138 // directly control-dependend on either the IfTrue or the IfFalse
145 // successor, because we know exactly how to update those uses. 139 // successor, because we know exactly how to update those uses.
146 // TODO(turbofan): Generalize this to all Phi/EffectPhi nodes using 140 // TODO(turbofan): Generalize this to all Phi/EffectPhi nodes using
147 // dominance/post-dominance on the sea of nodes. 141 // dominance/post-dominance on the sea of nodes.
148 if (edge.from()->op()->ControlInputCount() != 1) return false; 142 if (edge.from()->op()->ControlInputCount() != 1) return false;
149 Node* control = NodeProperties::GetControlInput(edge.from()); 143 Node* control = NodeProperties::GetControlInput(edge.from());
150 if (NodeProperties::IsPhi(edge.from())) { 144 if (NodeProperties::IsPhi(edge.from())) {
151 control = NodeProperties::GetControlInput(control, edge.index()); 145 control = NodeProperties::GetControlInput(control, edge.index());
152 } 146 }
153 if (control != if_true && control != if_false) return false; 147 if (control != matcher.IfTrue() && control != matcher.IfFalse())
148 return false;
154 } 149 }
155 phis.push_back(use); 150 phis.push_back(use);
156 } 151 }
157 BranchHint const hint = BranchHintOf(branch->op()); 152 BranchHint const hint = BranchHintOf(branch->op());
158 int const input_count = merge->op()->ControlInputCount(); 153 int const input_count = merge->op()->ControlInputCount();
159 DCHECK_LE(1, input_count); 154 DCHECK_LE(1, input_count);
160 Node** const inputs = zone()->NewArray<Node*>(2 * input_count); 155 Node** const inputs = zone()->NewArray<Node*>(2 * input_count);
161 Node** const merge_true_inputs = &inputs[0]; 156 Node** const merge_true_inputs = &inputs[0];
162 Node** const merge_false_inputs = &inputs[input_count]; 157 Node** const merge_false_inputs = &inputs[input_count];
163 for (int index = 0; index < input_count; ++index) { 158 for (int index = 0; index < input_count; ++index) {
(...skipping 14 matching lines...) Expand all
178 } 173 }
179 inputs[input_count] = merge_true; 174 inputs[input_count] = merge_true;
180 Node* phi_true = graph()->NewNode(phi->op(), input_count + 1, inputs); 175 Node* phi_true = graph()->NewNode(phi->op(), input_count + 1, inputs);
181 inputs[input_count] = merge_false; 176 inputs[input_count] = merge_false;
182 Node* phi_false = graph()->NewNode(phi->op(), input_count + 1, inputs); 177 Node* phi_false = graph()->NewNode(phi->op(), input_count + 1, inputs);
183 for (Edge edge : phi->use_edges()) { 178 for (Edge edge : phi->use_edges()) {
184 Node* control = NodeProperties::GetControlInput(edge.from()); 179 Node* control = NodeProperties::GetControlInput(edge.from());
185 if (NodeProperties::IsPhi(edge.from())) { 180 if (NodeProperties::IsPhi(edge.from())) {
186 control = NodeProperties::GetControlInput(control, edge.index()); 181 control = NodeProperties::GetControlInput(control, edge.index());
187 } 182 }
188 DCHECK(control == if_true || control == if_false); 183 DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
189 edge.UpdateTo((control == if_true) ? phi_true : phi_false); 184 edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
190 } 185 }
191 phi->Kill(); 186 phi->Kill();
192 } 187 }
193 // Fix up IfTrue and IfFalse and kill all dead nodes. 188 // Fix up IfTrue and IfFalse and kill all dead nodes.
194 if_false->ReplaceUses(merge_false); 189 matcher.IfFalse()->ReplaceUses(merge_false);
195 if_true->ReplaceUses(merge_true); 190 matcher.IfTrue()->ReplaceUses(merge_true);
196 if_false->Kill(); 191 matcher.IfFalse()->Kill();
197 if_true->Kill(); 192 matcher.IfTrue()->Kill();
198 branch->Kill(); 193 branch->Kill();
199 cond->Kill(); 194 cond->Kill();
200 merge->Kill(); 195 merge->Kill();
201 return true; 196 return true;
202 } 197 }
203 198
204 199
205 bool ControlFlowOptimizer::TryBuildSwitch(Node* node) { 200 bool ControlFlowOptimizer::TryBuildSwitch(Node* node) {
206 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); 201 DCHECK_EQ(IrOpcode::kBranch, node->opcode());
207 202
208 Node* branch = node; 203 Node* branch = node;
209 if (BranchHintOf(branch->op()) != BranchHint::kNone) return false; 204 if (BranchHintOf(branch->op()) != BranchHint::kNone) return false;
210 Node* cond = NodeProperties::GetValueInput(branch, 0); 205 Node* cond = NodeProperties::GetValueInput(branch, 0);
211 if (cond->opcode() != IrOpcode::kWord32Equal) return false; 206 if (cond->opcode() != IrOpcode::kWord32Equal) return false;
212 Int32BinopMatcher m(cond); 207 Int32BinopMatcher m(cond);
213 Node* index = m.left().node(); 208 Node* index = m.left().node();
214 if (!m.right().HasValue()) return false; 209 if (!m.right().HasValue()) return false;
215 int32_t value = m.right().Value(); 210 int32_t value = m.right().Value();
216 ZoneSet<int32_t> values(zone()); 211 ZoneSet<int32_t> values(zone());
217 values.insert(value); 212 values.insert(value);
218 213
219 Node* if_false; 214 Node* if_false;
220 Node* if_true; 215 Node* if_true;
221 while (true) { 216 while (true) {
222 Node* control_projections[2]; 217 BranchMatcher matcher(branch);
223 NodeProperties::CollectControlProjections(branch, control_projections, 2); 218 DCHECK(matcher.Matched());
224 if_true = control_projections[0]; 219
225 if_false = control_projections[1]; 220 if_true = matcher.IfTrue();
226 DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode()); 221 if_false = matcher.IfFalse();
227 DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
228 222
229 auto it = if_false->uses().begin(); 223 auto it = if_false->uses().begin();
230 if (it == if_false->uses().end()) break; 224 if (it == if_false->uses().end()) break;
231 Node* branch1 = *it++; 225 Node* branch1 = *it++;
232 if (branch1->opcode() != IrOpcode::kBranch) break; 226 if (branch1->opcode() != IrOpcode::kBranch) break;
233 if (BranchHintOf(branch1->op()) != BranchHint::kNone) break; 227 if (BranchHintOf(branch1->op()) != BranchHint::kNone) break;
234 if (it != if_false->uses().end()) break; 228 if (it != if_false->uses().end()) break;
235 Node* cond1 = branch1->InputAt(0); 229 Node* cond1 = branch1->InputAt(0);
236 if (cond1->opcode() != IrOpcode::kWord32Equal) break; 230 if (cond1->opcode() != IrOpcode::kWord32Equal) break;
237 Int32BinopMatcher m1(cond1); 231 Int32BinopMatcher m1(cond1);
(...skipping 11 matching lines...) Expand all
249 if_false->NullAllInputs(); 243 if_false->NullAllInputs();
250 Enqueue(if_true); 244 Enqueue(if_true);
251 245
252 branch = branch1; 246 branch = branch1;
253 value = value1; 247 value = value1;
254 values.insert(value); 248 values.insert(value);
255 } 249 }
256 250
257 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); 251 DCHECK_EQ(IrOpcode::kBranch, node->opcode());
258 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); 252 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
259 DCHECK_EQ(IrOpcode::kIfTrue, if_true->opcode());
260 DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
261 if (branch == node) { 253 if (branch == node) {
262 DCHECK_EQ(1u, values.size()); 254 DCHECK_EQ(1u, values.size());
263 return false; 255 return false;
264 } 256 }
265 DCHECK_LT(1u, values.size()); 257 DCHECK_LT(1u, values.size());
266 node->set_op(common()->Switch(values.size() + 1)); 258 node->set_op(common()->Switch(values.size() + 1));
267 node->ReplaceInput(0, index); 259 node->ReplaceInput(0, index);
268 if_true->set_op(common()->IfValue(value)); 260 if_true->set_op(common()->IfValue(value));
269 if_true->ReplaceInput(0, node); 261 if_true->ReplaceInput(0, node);
270 Enqueue(if_true); 262 Enqueue(if_true);
(...skipping 13 matching lines...) Expand all
284 Graph* ControlFlowOptimizer::graph() const { return jsgraph()->graph(); } 276 Graph* ControlFlowOptimizer::graph() const { return jsgraph()->graph(); }
285 277
286 278
287 MachineOperatorBuilder* ControlFlowOptimizer::machine() const { 279 MachineOperatorBuilder* ControlFlowOptimizer::machine() const {
288 return jsgraph()->machine(); 280 return jsgraph()->machine();
289 } 281 }
290 282
291 } // namespace compiler 283 } // namespace compiler
292 } // namespace internal 284 } // namespace internal
293 } // namespace v8 285 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/common-operator-reducer.cc ('k') | src/compiler/control-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698