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

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 425003004: Implement representation selection as part of SimplifiedLowering. Representation selection also req… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address review comments. Created 6 years, 4 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 | Annotate | Revision Log
OLDNEW
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 #include "src/compiler/simplified-lowering.h" 5 #include "src/compiler/simplified-lowering.h"
6 6
7 #include <deque>
8 #include <queue>
9
10 #include "src/compiler/common-operator.h"
7 #include "src/compiler/graph-inl.h" 11 #include "src/compiler/graph-inl.h"
8 #include "src/compiler/node-properties-inl.h" 12 #include "src/compiler/node-properties-inl.h"
13 #include "src/compiler/representation-change.h"
14 #include "src/compiler/simplified-lowering.h"
15 #include "src/compiler/simplified-operator.h"
9 #include "src/objects.h" 16 #include "src/objects.h"
10 17
11 namespace v8 { 18 namespace v8 {
12 namespace internal { 19 namespace internal {
13 namespace compiler { 20 namespace compiler {
14 21
22 // Macro for outputting trace information from representation inference.
23 #define TRACE(x) \
24 if (FLAG_trace_representation) PrintF x
25
26 // Representation selection and lowering of {Simplified} operators to machine
27 // operators are interwined. We use a fixpoint calculation to compute both the
28 // output representation and the best possible lowering for {Simplified} nodes.
29 // Representation change insertion ensures that all values are in the correct
30 // machine representation after this phase, as dictated by the machine
31 // operators themselves.
32 enum Phase {
33 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
34 // backwards from uses to definitions, around cycles in phis, according
35 // to local rules for each operator.
36 // During this phase, the usage information for a node determines the best
37 // possible lowering for each operator so far, and that in turn determines
38 // the output representation.
39 // Therefore, to be correct, this phase must iterate to a fixpoint before
40 // the next phase can begin.
41 PROPAGATE,
42
43 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some
44 // operators for some nodes, expanding some nodes to multiple nodes, or
45 // removing some (redundant) nodes.
46 // During this phase, use the {RepresentationChanger} to insert
47 // representation changes between uses that demand a particular
48 // representation and nodes that produce a different representation.
49 LOWER
50 };
51
52
53 class RepresentationSelector {
54 public:
55 // Information for each node tracked during the fixpoint.
56 struct NodeInfo {
57 RepTypeUnion use : 14; // Union of all usages for the node.
58 bool queued : 1; // Bookkeeping for the traversal.
59 bool visited : 1; // Bookkeeping for the traversal.
60 RepTypeUnion output : 16; // Output type of the node.
61 };
62
63 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
64 RepresentationChanger* changer)
65 : jsgraph_(jsgraph),
66 zone_(zone),
67 count_(jsgraph->graph()->NodeCount()),
68 info_(zone->NewArray<NodeInfo>(count_)),
69 nodes_(NodeVector::allocator_type(zone)),
70 replacements_(NodeVector::allocator_type(zone)),
71 contains_js_nodes_(false),
72 phase_(PROPAGATE),
73 changer_(changer),
74 queue_(std::deque<Node*, NodePtrZoneAllocator>(
75 NodePtrZoneAllocator(zone))) {
76 memset(info_, 0, sizeof(NodeInfo) * count_);
77 }
78
79 void Run(SimplifiedLowering* lowering) {
80 // Run propagation phase to a fixpoint.
81 TRACE(("--{Propagation phase}--\n"));
82 phase_ = PROPAGATE;
83 Enqueue(jsgraph_->graph()->end());
84 // Process nodes from the queue until it is empty.
85 while (!queue_.empty()) {
86 Node* node = queue_.front();
87 NodeInfo* info = GetInfo(node);
88 queue_.pop();
89 info->queued = false;
90 TRACE((" visit #%d: %s\n", node->id(), node->op()->mnemonic()));
91 VisitNode(node, info->use, NULL);
92 TRACE((" ==> output "));
93 PrintInfo(info->output);
94 TRACE(("\n"));
95 }
96
97 // Run lowering and change insertion phase.
98 TRACE(("--{Simplified lowering phase}--\n"));
99 phase_ = LOWER;
100 // Process nodes from the collected {nodes_} vector.
101 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
102 Node* node = *i;
103 TRACE((" visit #%d: %s\n", node->id(), node->op()->mnemonic()));
104 // Reuse {VisitNode()} so the representation rules are in one place.
105 VisitNode(node, GetUseInfo(node), lowering);
106 }
107
108 // Perform the final replacements.
109 for (NodeVector::iterator i = replacements_.begin();
110 i != replacements_.end(); ++i) {
111 Node* node = *i;
112 Node* replacement = *(++i);
113 node->ReplaceUses(replacement);
114 }
115 }
116
117 // Enqueue {node} if the {use} contains new information for that node.
118 // Add {node} to {nodes_} if this is the first time it's been visited.
119 void Enqueue(Node* node, RepTypeUnion use = 0) {
120 if (phase_ != PROPAGATE) return;
121 NodeInfo* info = GetInfo(node);
122 if (!info->visited) {
123 // First visit of this node.
124 info->visited = true;
125 info->queued = true;
126 nodes_.push_back(node);
127 queue_.push(node);
128 TRACE((" initial: "));
129 info->use |= use;
130 PrintUseInfo(node);
131 return;
132 }
133 TRACE((" queue?: "));
134 PrintUseInfo(node);
135 if ((info->use & use) != use) {
136 // New usage information for the node is available.
137 if (!info->queued) {
138 queue_.push(node);
139 info->queued = true;
140 TRACE((" added: "));
141 } else {
142 TRACE((" inqueue: "));
143 }
144 info->use |= use;
145 PrintUseInfo(node);
146 }
147 }
148
149 bool lower() { return phase_ == LOWER; }
150
151 void Enqueue(Node* node, RepType use) {
152 Enqueue(node, static_cast<RepTypeUnion>(use));
153 }
154
155 void SetOutput(Node* node, RepTypeUnion output) {
156 // Every node should have at most one output representation. Note that
157 // phis can have 0, if they have not been used in a representation-inducing
158 // instruction.
159 DCHECK((output & rMask) == 0 || IsPowerOf2(output & rMask));
160 GetInfo(node)->output = output;
161 }
162
163 bool BothInputsAre(Node* node, Type* type) {
164 DCHECK_EQ(2, node->InputCount());
165 return NodeProperties::GetBounds(node->InputAt(0)).upper->Is(type) &&
166 NodeProperties::GetBounds(node->InputAt(1)).upper->Is(type);
167 }
168
169 void ProcessInput(Node* node, int index, RepTypeUnion use) {
170 Node* input = node->InputAt(index);
171 if (phase_ == PROPAGATE) {
172 // In the propagate phase, propagate the usage information backward.
173 Enqueue(input, use);
174 } else {
175 // In the change phase, insert a change before the use if necessary.
176 RepTypeUnion output = GetInfo(input)->output;
177 if ((output & rMask & use) == 0) {
178 // Output representation doesn't match usage.
179 TRACE((" change: #%d:%s(@%d #%d:%s) ", node->id(),
180 node->op()->mnemonic(), index, input->id(),
181 input->op()->mnemonic()));
182 TRACE((" from "));
183 PrintInfo(output);
184 TRACE((" to "));
185 PrintInfo(use);
186 TRACE(("\n"));
187 Node* n = changer_->GetRepresentationFor(input, output, use);
188 node->ReplaceInput(index, n);
189 }
190 }
191 }
192
193 static const RepTypeUnion kFloat64 = rFloat64 | tNumber;
194 static const RepTypeUnion kInt32 = rWord32 | tInt32;
195 static const RepTypeUnion kUint32 = rWord32 | tUint32;
196 static const RepTypeUnion kInt64 = rWord64 | tInt64;
197 static const RepTypeUnion kUint64 = rWord64 | tUint64;
198 static const RepTypeUnion kAnyTagged = rTagged | tAny;
199
200 // The default, most general visitation case. For {node}, process all value,
201 // context, effect, and control inputs, assuming that value inputs should have
202 // {rTagged} representation and can observe all output values {tAny}.
203 void VisitInputs(Node* node) {
204 InputIter i = node->inputs().begin();
205 for (int j = OperatorProperties::GetValueInputCount(node->op()); j > 0;
206 ++i, j--) {
207 ProcessInput(node, i.index(), kAnyTagged); // Value inputs
208 }
209 for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0;
210 ++i, j--) {
211 ProcessInput(node, i.index(), kAnyTagged); // Context inputs
212 }
213 for (int j = OperatorProperties::GetEffectInputCount(node->op()); j > 0;
214 ++i, j--) {
215 Enqueue(*i); // Effect inputs: just visit
216 }
217 for (int j = OperatorProperties::GetControlInputCount(node->op()); j > 0;
218 ++i, j--) {
219 Enqueue(*i); // Control inputs: just visit
220 }
221 SetOutput(node, kAnyTagged);
222 }
223
224 // Helper for binops of the I x I -> O variety.
225 void VisitBinop(Node* node, RepTypeUnion input_use, RepTypeUnion output) {
226 DCHECK_EQ(2, node->InputCount());
227 ProcessInput(node, 0, input_use);
228 ProcessInput(node, 1, input_use);
229 SetOutput(node, output);
230 }
231
232 // Helper for unops of the I -> O variety.
233 void VisitUnop(Node* node, RepTypeUnion input_use, RepTypeUnion output) {
234 DCHECK_EQ(1, node->InputCount());
235 ProcessInput(node, 0, input_use);
236 SetOutput(node, output);
237 }
238
239 // Helper for leaf nodes.
240 void VisitLeaf(Node* node, RepTypeUnion output) {
241 DCHECK_EQ(0, node->InputCount());
242 SetOutput(node, output);
243 }
244
245 // Helpers for specific types of binops.
246 void VisitFloat64Binop(Node* node) { VisitBinop(node, kFloat64, kFloat64); }
247 void VisitInt32Binop(Node* node) { VisitBinop(node, kInt32, kInt32); }
248 void VisitUint32Binop(Node* node) { VisitBinop(node, kUint32, kUint32); }
249 void VisitInt64Binop(Node* node) { VisitBinop(node, kInt64, kInt64); }
250 void VisitUint64Binop(Node* node) { VisitBinop(node, kUint64, kUint64); }
251 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kFloat64, rBit); }
252 void VisitInt32Cmp(Node* node) { VisitBinop(node, kInt32, rBit); }
253 void VisitUint32Cmp(Node* node) { VisitBinop(node, kUint32, rBit); }
254 void VisitInt64Cmp(Node* node) { VisitBinop(node, kInt64, rBit); }
255 void VisitUint64Cmp(Node* node) { VisitBinop(node, kUint64, rBit); }
256
257 // Helper for handling phis.
258 void VisitPhi(Node* node, RepTypeUnion use) {
259 // First, propagate the usage information to inputs of the phi.
260 int values = OperatorProperties::GetValueInputCount(node->op());
261 Node::Inputs inputs = node->inputs();
262 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
263 ++iter, --values) {
264 // Propagate {use} of the phi to value inputs, and 0 to control.
265 ProcessInput(node, iter.index(), values > 0 ? use : 0);
266 }
267 // Phis adapt to whatever output representation their uses demand,
268 // pushing representation changes to their inputs.
269 RepTypeUnion use_rep = GetUseInfo(node) & rMask;
270 RepTypeUnion use_type = GetUseInfo(node) & tMask;
271 RepTypeUnion rep = 0;
272 if (use_rep & rTagged) {
273 rep = rTagged; // Tagged overrides everything.
274 } else if (use_rep & rFloat64) {
275 rep = rFloat64;
276 } else if (use_rep & rWord64) {
277 rep = rWord64;
278 } else if (use_rep & rWord32) {
279 rep = rWord32;
280 } else if (use_rep & rBit) {
281 rep = rBit;
282 } else {
283 // There was no representation associated with any of the uses.
284 // Select the best one based on the phi's type.
285 // phi. TODO(titzer): Select the best one based on the phi's type,
286 // not on the usage.
287 if (use_type & tAny) {
288 rep = rTagged;
289 } else if (use_type & tNumber) {
290 rep = rFloat64;
291 } else if (use_type & tInt64 || use_type & tUint64) {
292 rep = rWord64;
293 } else if (use_type & tInt32 || use_type & tUint32) {
294 rep = rWord32;
295 } else if (use_type & tBool) {
296 rep = rBit;
297 } else {
298 UNREACHABLE(); // should have at least a usage type!
299 }
300 }
301 // Preserve the usage type, but set the representation.
302 Type* upper = NodeProperties::GetBounds(node).upper;
303 SetOutput(node, rep | changer_->TypeFromUpperBound(upper));
304 }
305
306 Operator* Int32Op(Node* node) {
307 return changer_->Int32OperatorFor(node->opcode());
308 }
309
310 Operator* Uint32Op(Node* node) {
311 return changer_->Uint32OperatorFor(node->opcode());
312 }
313
314 Operator* Float64Op(Node* node) {
315 return changer_->Float64OperatorFor(node->opcode());
316 }
317
318 // Dispatching routine for visiting the node {node} with the usage {use}.
319 // Depending on the operator, propagate new usage info to the inputs.
320 void VisitNode(Node* node, RepTypeUnion use, SimplifiedLowering* lowering) {
321 switch (node->opcode()) {
322 //------------------------------------------------------------------
323 // Common operators.
324 //------------------------------------------------------------------
325 case IrOpcode::kStart:
326 case IrOpcode::kDead:
327 return VisitLeaf(node, rBit);
328 case IrOpcode::kParameter: {
329 // TODO(titzer): use representation from linkage.
330 Type* upper = NodeProperties::GetBounds(node).upper;
331 ProcessInput(node, 0, 0);
332 SetOutput(node, rTagged | changer_->TypeFromUpperBound(upper));
333 return;
334 }
335 case IrOpcode::kInt32Constant:
336 return VisitLeaf(node, rWord32);
337 case IrOpcode::kInt64Constant:
338 return VisitLeaf(node, rWord64);
339 case IrOpcode::kFloat64Constant:
340 return VisitLeaf(node, rFloat64);
341 case IrOpcode::kExternalConstant:
342 return VisitLeaf(node, rPtr);
343 case IrOpcode::kNumberConstant:
344 return VisitLeaf(node, rTagged);
345 case IrOpcode::kHeapConstant:
346 return VisitLeaf(node, rTagged);
347
348 case IrOpcode::kEnd:
349 case IrOpcode::kIfTrue:
350 case IrOpcode::kIfFalse:
351 case IrOpcode::kReturn:
352 case IrOpcode::kMerge:
353 case IrOpcode::kThrow:
354 return VisitInputs(node); // default visit for all node inputs.
355
356 case IrOpcode::kBranch:
357 ProcessInput(node, 0, rBit);
358 Enqueue(NodeProperties::GetControlInput(node, 0));
359 break;
360 case IrOpcode::kPhi:
361 return VisitPhi(node, use);
362
363 //------------------------------------------------------------------
364 // JavaScript operators.
365 //------------------------------------------------------------------
366 // For now, we assume that all JS operators were too complex to lower
367 // to Simplified and that they will always require tagged value inputs and
368 // produce tagged value outputs.
369 // TODO(turbofan): it might be possible to lower some JSOperators here,
370 // but that responsibility really lies in the typed lowering phase.
371 #define DEFINE_JS_CASE(x) case IrOpcode::k##x:
372 JS_OP_LIST(DEFINE_JS_CASE)
373 #undef DEFINE_JS_CASE
374 contains_js_nodes_ = true;
375 VisitInputs(node);
376 return SetOutput(node, rTagged);
377
378 //------------------------------------------------------------------
379 // Simplified operators.
380 //------------------------------------------------------------------
381 case IrOpcode::kBooleanNot: {
382 if (lower()) {
383 RepTypeUnion input = GetInfo(node->InputAt(0))->output;
384 if (input & rBit) {
385 // BooleanNot(x: rBit) => WordEqual(x, #0)
386 node->set_op(lowering->machine()->WordEqual());
387 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
388 } else {
389 // BooleanNot(x: rTagged) => WordEqual(x, #false)
390 node->set_op(lowering->machine()->WordEqual());
391 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
392 }
393 } else {
394 // No representation requirement, since we handle both during
395 // lowering.
396 ProcessInput(node, 0, tBool);
397 SetOutput(node, rBit);
398 }
399 break;
400 }
401 case IrOpcode::kNumberEqual:
402 case IrOpcode::kNumberLessThan:
403 case IrOpcode::kNumberLessThanOrEqual: {
404 // Number comparisons reduce to integer comparisons for integer inputs.
405 if (BothInputsAre(node, Type::Signed32())) {
406 // => signed Int32Cmp
407 VisitInt32Cmp(node);
408 if (lower()) node->set_op(Int32Op(node));
409 } else if (BothInputsAre(node, Type::Unsigned32())) {
410 // => unsigned Int32Cmp
411 VisitUint32Cmp(node);
412 if (lower()) node->set_op(Uint32Op(node));
413 } else {
414 // => Float64Cmp
415 VisitFloat64Cmp(node);
416 if (lower()) node->set_op(Float64Op(node));
417 }
418 break;
419 }
420 case IrOpcode::kNumberAdd:
421 case IrOpcode::kNumberSubtract: {
422 // Add and subtract reduce to Int32Add/Sub if the inputs
423 // are already integers and all uses are truncating.
424 if (BothInputsAre(node, Type::Signed32()) &&
425 (use & (tUint32 | tNumber | tAny)) == 0) {
426 // => signed Int32Add/Sub
427 VisitInt32Binop(node);
428 if (lower()) node->set_op(Int32Op(node));
429 } else if (BothInputsAre(node, Type::Unsigned32()) &&
430 (use & (tInt32 | tNumber | tAny)) == 0) {
431 // => unsigned Int32Add/Sub
432 VisitUint32Binop(node);
433 if (lower()) node->set_op(Uint32Op(node));
434 } else {
435 // => Float64Add/Sub
436 VisitFloat64Binop(node);
437 if (lower()) node->set_op(Float64Op(node));
438 }
439 break;
440 }
441 case IrOpcode::kNumberMultiply:
442 case IrOpcode::kNumberDivide:
443 case IrOpcode::kNumberModulus: {
444 // Float64Mul/Div/Mod
445 VisitFloat64Binop(node);
446 if (lower()) node->set_op(Float64Op(node));
447 break;
448 }
449 case IrOpcode::kNumberToInt32: {
450 RepTypeUnion use_rep = use & rMask;
451 if (lower()) {
452 RepTypeUnion in = GetInfo(node->InputAt(0))->output;
453 if ((in & tMask) == tInt32 || (in & rMask) == rWord32) {
454 // If the input has type int32, or is already a word32, just change
455 // representation if necessary.
456 VisitUnop(node, tInt32 | use_rep, tInt32 | use_rep);
457 DeferReplacement(node, node->InputAt(0));
458 } else {
459 // Require the input in float64 format and perform truncation.
460 // TODO(turbofan): could also avoid the truncation with a tag check.
461 VisitUnop(node, tInt32 | rFloat64, tInt32 | rWord32);
462 // TODO(titzer): should be a truncation.
463 node->set_op(lowering->machine()->ChangeFloat64ToInt32());
464 }
465 } else {
466 // Propagate a type to the input, but not a representation.
467 VisitUnop(node, tInt32, tInt32 | use_rep);
468 }
469 break;
470 }
471 case IrOpcode::kNumberToUint32: {
472 RepTypeUnion use_rep = use & rMask;
473 if (lower()) {
474 RepTypeUnion in = GetInfo(node->InputAt(0))->output;
475 if ((in & tMask) == tUint32 || (in & rMask) == rWord32) {
476 // The input has type int32, just change representation.
477 VisitUnop(node, tUint32 | use_rep, tUint32 | use_rep);
478 DeferReplacement(node, node->InputAt(0));
479 } else {
480 // Require the input in float64 format to perform truncation.
481 // TODO(turbofan): could also avoid the truncation with a tag check.
482 VisitUnop(node, tUint32 | rFloat64, tUint32 | rWord32);
483 // TODO(titzer): should be a truncation.
484 node->set_op(lowering->machine()->ChangeFloat64ToUint32());
485 }
486 } else {
487 // Propagate a type to the input, but not a representation.
488 VisitUnop(node, tUint32, tUint32 | use_rep);
489 }
490 break;
491 }
492 case IrOpcode::kReferenceEqual: {
493 VisitBinop(node, kAnyTagged, rBit);
494 if (lower()) node->set_op(lowering->machine()->WordEqual());
495 break;
496 }
497 case IrOpcode::kStringEqual: {
498 VisitBinop(node, kAnyTagged, rBit);
499 // TODO(titzer): lower StringEqual to stub/runtime call.
500 break;
501 }
502 case IrOpcode::kStringLessThan: {
503 VisitBinop(node, kAnyTagged, rBit);
504 // TODO(titzer): lower StringLessThan to stub/runtime call.
505 break;
506 }
507 case IrOpcode::kStringLessThanOrEqual: {
508 VisitBinop(node, kAnyTagged, rBit);
509 // TODO(titzer): lower StringLessThanOrEqual to stub/runtime call.
510 break;
511 }
512 case IrOpcode::kStringAdd: {
513 VisitBinop(node, kAnyTagged, kAnyTagged);
514 // TODO(titzer): lower StringAdd to stub/runtime call.
515 break;
516 }
517 case IrOpcode::kLoadField: {
518 FieldAccess access = FieldAccessOf(node->op());
519 ProcessInput(node, 0, changer_->TypeForBasePointer(access));
520 SetOutput(node, changer_->TypeForField(access));
521 if (lower()) lowering->DoLoadField(node);
522 break;
523 }
524 case IrOpcode::kStoreField: {
525 FieldAccess access = FieldAccessOf(node->op());
526 ProcessInput(node, 0, changer_->TypeForBasePointer(access));
527 ProcessInput(node, 1, changer_->TypeForField(access));
528 SetOutput(node, 0);
529 if (lower()) lowering->DoStoreField(node);
530 break;
531 }
532 case IrOpcode::kLoadElement: {
533 ElementAccess access = ElementAccessOf(node->op());
534 ProcessInput(node, 0, changer_->TypeForBasePointer(access));
535 ProcessInput(node, 1, kInt32); // element index
536 SetOutput(node, changer_->TypeForElement(access));
537 if (lower()) lowering->DoLoadElement(node);
538 break;
539 }
540 case IrOpcode::kStoreElement: {
541 ElementAccess access = ElementAccessOf(node->op());
542 ProcessInput(node, 0, changer_->TypeForBasePointer(access));
543 ProcessInput(node, 1, kInt32); // element index
544 ProcessInput(node, 2, changer_->TypeForElement(access));
545 SetOutput(node, 0);
546 if (lower()) lowering->DoStoreElement(node);
547 break;
548 }
549
550 //------------------------------------------------------------------
551 // Machine-level operators.
552 //------------------------------------------------------------------
553 case IrOpcode::kLoad: {
554 // TODO(titzer): machine loads/stores need to know BaseTaggedness!?
555 RepType tBase = rTagged;
556 MachineRepresentation rep = OpParameter<MachineRepresentation>(node);
557 ProcessInput(node, 0, tBase); // pointer or object
558 ProcessInput(node, 1, kInt32); // index
559 SetOutput(node, changer_->TypeForMachineRepresentation(rep));
560 break;
561 }
562 case IrOpcode::kStore: {
563 // TODO(titzer): machine loads/stores need to know BaseTaggedness!?
564 RepType tBase = rTagged;
565 StoreRepresentation rep = OpParameter<StoreRepresentation>(node);
566 ProcessInput(node, 0, tBase); // pointer or object
567 ProcessInput(node, 1, kInt32); // index
568 ProcessInput(node, 2, changer_->TypeForMachineRepresentation(rep.rep));
569 SetOutput(node, 0);
570 break;
571 }
572 case IrOpcode::kWord32Shr:
573 // We use unsigned int32 as the output type for shift right, though
574 // technically it doesn't have a sign. Because JavaScript.
575 return VisitBinop(node, rWord32, rWord32 | tUint32);
576 case IrOpcode::kWord32And:
577 case IrOpcode::kWord32Or:
578 case IrOpcode::kWord32Xor:
579 case IrOpcode::kWord32Shl:
580 case IrOpcode::kWord32Sar:
581 // We use signed int32 as the output type for these word32 operations,
582 // though technically they don't have a sign. Because JavaScript.
583 return VisitBinop(node, rWord32, rWord32 | tInt32);
584 case IrOpcode::kWord32Equal:
585 return VisitBinop(node, rWord32, rBit);
586
587 case IrOpcode::kInt32Add:
588 case IrOpcode::kInt32Sub:
589 case IrOpcode::kInt32Mul:
590 case IrOpcode::kInt32Div:
591 case IrOpcode::kInt32Mod:
592 return VisitInt32Binop(node);
593 case IrOpcode::kInt32UDiv:
594 case IrOpcode::kInt32UMod:
595 return VisitUint32Binop(node);
596 case IrOpcode::kInt32LessThan:
597 case IrOpcode::kInt32LessThanOrEqual:
598 return VisitInt32Cmp(node);
599
600 case IrOpcode::kUint32LessThan:
601 case IrOpcode::kUint32LessThanOrEqual:
602 return VisitUint32Cmp(node);
603
604 case IrOpcode::kInt64Add:
605 case IrOpcode::kInt64Sub:
606 case IrOpcode::kInt64Mul:
607 case IrOpcode::kInt64Div:
608 case IrOpcode::kInt64Mod:
609 return VisitInt64Binop(node);
610 case IrOpcode::kInt64LessThan:
611 case IrOpcode::kInt64LessThanOrEqual:
612 return VisitInt64Cmp(node);
613
614 case IrOpcode::kInt64UDiv:
615 case IrOpcode::kInt64UMod:
616 return VisitUint64Binop(node);
617
618 case IrOpcode::kWord64And:
619 case IrOpcode::kWord64Or:
620 case IrOpcode::kWord64Xor:
621 case IrOpcode::kWord64Shl:
622 case IrOpcode::kWord64Shr:
623 case IrOpcode::kWord64Sar:
624 return VisitBinop(node, rWord64, rWord64);
625 case IrOpcode::kWord64Equal:
626 return VisitBinop(node, rWord64, rBit);
627
628 case IrOpcode::kConvertInt32ToInt64:
629 return VisitUnop(node, tInt32 | rWord32, tInt32 | rWord64);
630 case IrOpcode::kConvertInt64ToInt32:
631 return VisitUnop(node, tInt64 | rWord64, tInt32 | rWord32);
632
633 case IrOpcode::kChangeInt32ToFloat64:
634 return VisitUnop(node, tInt32 | rWord32, tInt32 | rFloat64);
635 case IrOpcode::kChangeUint32ToFloat64:
636 return VisitUnop(node, tUint32 | rWord32, tUint32 | rFloat64);
637 case IrOpcode::kChangeFloat64ToInt32:
638 return VisitUnop(node, tInt32 | rFloat64, tInt32 | rWord32);
639 case IrOpcode::kChangeFloat64ToUint32:
640 return VisitUnop(node, tUint32 | rFloat64, tUint32 | rWord32);
641
642 case IrOpcode::kFloat64Add:
643 case IrOpcode::kFloat64Sub:
644 case IrOpcode::kFloat64Mul:
645 case IrOpcode::kFloat64Div:
646 case IrOpcode::kFloat64Mod:
647 return VisitFloat64Binop(node);
648 case IrOpcode::kFloat64Equal:
649 case IrOpcode::kFloat64LessThan:
650 case IrOpcode::kFloat64LessThanOrEqual:
651 return VisitFloat64Cmp(node);
652 default:
653 VisitInputs(node);
654 break;
655 }
656 }
657
658 void DeferReplacement(Node* node, Node* replacement) {
659 if (replacement->id() < count_) {
660 // Replace with a previously existing node eagerly.
661 node->ReplaceUses(replacement);
662 } else {
663 // Otherwise, we are replacing a node with a representation change.
664 // Such a substitution must be done after all lowering is done, because
665 // new nodes do not have {NodeInfo} entries, and that would confuse
666 // the representation change insertion for uses of it.
667 replacements_.push_back(node);
668 replacements_.push_back(replacement);
669 }
670 // TODO(titzer) node->RemoveAllInputs(); // Node is now dead.
671 }
672
673 void PrintUseInfo(Node* node) {
674 TRACE(("#%d:%-20s ", node->id(), node->op()->mnemonic()));
675 PrintInfo(GetUseInfo(node));
676 TRACE(("\n"));
677 }
678
679 void PrintInfo(RepTypeUnion info) {
680 if (FLAG_trace_representation) {
681 char buf[REP_TYPE_STRLEN];
682 RenderRepTypeUnion(buf, info);
683 TRACE(("%s", buf));
684 }
685 }
686
687 private:
688 JSGraph* jsgraph_;
689 Zone* zone_;
690 int count_; // number of nodes in the graph
691 NodeInfo* info_; // node id -> usage information
692 NodeVector nodes_; // collected nodes
693 NodeVector replacements_; // replacements to be done after lowering
694 bool contains_js_nodes_; // {true} if a JS operator was seen
695 Phase phase_; // current phase of algorithm
696 RepresentationChanger* changer_; // for inserting representation changes
697
698 std::queue<Node*, std::deque<Node*, NodePtrZoneAllocator> > queue_;
699
700 NodeInfo* GetInfo(Node* node) {
701 DCHECK(node->id() >= 0);
702 DCHECK(node->id() < count_);
703 return &info_[node->id()];
704 }
705
706 RepTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; }
707 };
708
709
15 Node* SimplifiedLowering::IsTagged(Node* node) { 710 Node* SimplifiedLowering::IsTagged(Node* node) {
16 // TODO(titzer): factor this out to a TaggingScheme abstraction. 711 // TODO(titzer): factor this out to a TaggingScheme abstraction.
17 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. 712 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit.
18 return graph()->NewNode(machine()->WordAnd(), node, 713 return graph()->NewNode(machine()->WordAnd(), node,
19 jsgraph()->Int32Constant(kSmiTagMask)); 714 jsgraph()->Int32Constant(kSmiTagMask));
20 } 715 }
21 716
22 717
718 void SimplifiedLowering::LowerAllNodes() {
719 SimplifiedOperatorBuilder simplified(graph()->zone());
720 RepresentationChanger changer(jsgraph(), &simplified, machine(),
721 graph()->zone()->isolate());
722 RepresentationSelector selector(jsgraph(), zone(), &changer);
723 selector.Run(this);
724
725 LoweringBuilder::LowerAllNodes();
726 }
727
728
23 Node* SimplifiedLowering::Untag(Node* node) { 729 Node* SimplifiedLowering::Untag(Node* node) {
24 // TODO(titzer): factor this out to a TaggingScheme abstraction. 730 // TODO(titzer): factor this out to a TaggingScheme abstraction.
25 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); 731 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize);
26 return graph()->NewNode(machine()->WordSar(), node, shift_amount); 732 return graph()->NewNode(machine()->WordSar(), node, shift_amount);
27 } 733 }
28 734
29 735
30 Node* SimplifiedLowering::SmiTag(Node* node) { 736 Node* SimplifiedLowering::SmiTag(Node* node) {
31 // TODO(titzer): factor this out to a TaggingScheme abstraction. 737 // TODO(titzer): factor this out to a TaggingScheme abstraction.
32 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); 738 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 864
159 865
160 void SimplifiedLowering::DoChangeFloat64ToTagged(Node* node, Node* effect, 866 void SimplifiedLowering::DoChangeFloat64ToTagged(Node* node, Node* effect,
161 Node* control) { 867 Node* control) {
162 return; // TODO(titzer): need to call runtime to allocate in one branch 868 return; // TODO(titzer): need to call runtime to allocate in one branch
163 } 869 }
164 870
165 871
166 void SimplifiedLowering::DoChangeBoolToBit(Node* node, Node* effect, 872 void SimplifiedLowering::DoChangeBoolToBit(Node* node, Node* effect,
167 Node* control) { 873 Node* control) {
168 Node* val = node->InputAt(0); 874 Node* cmp = graph()->NewNode(machine()->WordEqual(), node->InputAt(0),
169 Operator* op = 875 jsgraph()->TrueConstant());
170 kPointerSize == 8 ? machine()->Word64Equal() : machine()->Word32Equal();
171 Node* cmp = graph()->NewNode(op, val, jsgraph()->TrueConstant());
172 node->ReplaceUses(cmp); 876 node->ReplaceUses(cmp);
173 } 877 }
174 878
175 879
176 void SimplifiedLowering::DoChangeBitToBool(Node* node, Node* effect, 880 void SimplifiedLowering::DoChangeBitToBool(Node* node, Node* effect,
177 Node* control) { 881 Node* control) {
178 Node* val = node->InputAt(0); 882 Node* val = node->InputAt(0);
179 Node* branch = graph()->NewNode(common()->Branch(), val, control); 883 Node* branch = graph()->NewNode(common()->Branch(), val, control);
180 884
181 // true branch. 885 // true branch.
(...skipping 15 matching lines...) Expand all
197 Type* type) { 901 Type* type) {
198 // TODO(turbofan): skip write barriers for Smis, etc. 902 // TODO(turbofan): skip write barriers for Smis, etc.
199 if (base_is_tagged == kTaggedBase && representation == kMachineTagged) { 903 if (base_is_tagged == kTaggedBase && representation == kMachineTagged) {
200 // Write barriers are only for writes into heap objects (i.e. tagged base). 904 // Write barriers are only for writes into heap objects (i.e. tagged base).
201 return kFullWriteBarrier; 905 return kFullWriteBarrier;
202 } 906 }
203 return kNoWriteBarrier; 907 return kNoWriteBarrier;
204 } 908 }
205 909
206 910
207 void SimplifiedLowering::DoLoadField(Node* node, Node* effect, Node* control) { 911 void SimplifiedLowering::DoLoadField(Node* node) {
208 const FieldAccess& access = FieldAccessOf(node->op()); 912 const FieldAccess& access = FieldAccessOf(node->op());
209 node->set_op(machine_.Load(access.representation)); 913 node->set_op(machine_.Load(access.representation));
210 Node* offset = jsgraph()->Int32Constant(access.offset - access.tag()); 914 Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
211 node->InsertInput(zone(), 1, offset); 915 node->InsertInput(zone(), 1, offset);
212 } 916 }
213 917
214 918
215 void SimplifiedLowering::DoStoreField(Node* node, Node* effect, Node* control) { 919 void SimplifiedLowering::DoStoreField(Node* node) {
216 const FieldAccess& access = FieldAccessOf(node->op()); 920 const FieldAccess& access = FieldAccessOf(node->op());
217 WriteBarrierKind kind = ComputeWriteBarrierKind( 921 WriteBarrierKind kind = ComputeWriteBarrierKind(
218 access.base_is_tagged, access.representation, access.type); 922 access.base_is_tagged, access.representation, access.type);
219 node->set_op(machine_.Store(access.representation, kind)); 923 node->set_op(machine_.Store(access.representation, kind));
220 Node* offset = jsgraph()->Int32Constant(access.offset - access.tag()); 924 Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
221 node->InsertInput(zone(), 1, offset); 925 node->InsertInput(zone(), 1, offset);
222 } 926 }
223 927
224 928
225 Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, 929 Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access,
(...skipping 24 matching lines...) Expand all
250 index = graph()->NewNode(machine()->Int32Mul(), 954 index = graph()->NewNode(machine()->Int32Mul(),
251 jsgraph()->Int32Constant(element_size), index); 955 jsgraph()->Int32Constant(element_size), index);
252 } 956 }
253 int fixed_offset = access.header_size - access.tag(); 957 int fixed_offset = access.header_size - access.tag();
254 if (fixed_offset == 0) return index; 958 if (fixed_offset == 0) return index;
255 return graph()->NewNode(machine()->Int32Add(), 959 return graph()->NewNode(machine()->Int32Add(),
256 jsgraph()->Int32Constant(fixed_offset), index); 960 jsgraph()->Int32Constant(fixed_offset), index);
257 } 961 }
258 962
259 963
260 void SimplifiedLowering::DoLoadElement(Node* node, Node* effect, 964 void SimplifiedLowering::DoLoadElement(Node* node) {
261 Node* control) {
262 const ElementAccess& access = ElementAccessOf(node->op()); 965 const ElementAccess& access = ElementAccessOf(node->op());
263 node->set_op(machine_.Load(access.representation)); 966 node->set_op(machine_.Load(access.representation));
264 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); 967 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
265 } 968 }
266 969
267 970
268 void SimplifiedLowering::DoStoreElement(Node* node, Node* effect, 971 void SimplifiedLowering::DoStoreElement(Node* node) {
269 Node* control) {
270 const ElementAccess& access = ElementAccessOf(node->op()); 972 const ElementAccess& access = ElementAccessOf(node->op());
271 WriteBarrierKind kind = ComputeWriteBarrierKind( 973 WriteBarrierKind kind = ComputeWriteBarrierKind(
272 access.base_is_tagged, access.representation, access.type); 974 access.base_is_tagged, access.representation, access.type);
273 node->set_op(machine_.Store(access.representation, kind)); 975 node->set_op(machine_.Store(access.representation, kind));
274 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); 976 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
275 } 977 }
276 978
277 979
278 void SimplifiedLowering::Lower(Node* node) { 980 void SimplifiedLowering::Lower(Node* node) {}
279 Node* start = graph()->start(); 981
982
983 void SimplifiedLowering::LowerChange(Node* node, Node* effect, Node* control) {
280 switch (node->opcode()) { 984 switch (node->opcode()) {
281 case IrOpcode::kBooleanNot:
282 case IrOpcode::kNumberEqual:
283 case IrOpcode::kNumberLessThan:
284 case IrOpcode::kNumberLessThanOrEqual:
285 case IrOpcode::kNumberAdd:
286 case IrOpcode::kNumberSubtract:
287 case IrOpcode::kNumberMultiply:
288 case IrOpcode::kNumberDivide:
289 case IrOpcode::kNumberModulus:
290 case IrOpcode::kNumberToInt32:
291 case IrOpcode::kNumberToUint32:
292 case IrOpcode::kReferenceEqual:
293 case IrOpcode::kStringEqual:
294 case IrOpcode::kStringLessThan:
295 case IrOpcode::kStringLessThanOrEqual:
296 case IrOpcode::kStringAdd:
297 break;
298 case IrOpcode::kChangeTaggedToInt32: 985 case IrOpcode::kChangeTaggedToInt32:
299 DoChangeTaggedToUI32(node, start, start, true); 986 DoChangeTaggedToUI32(node, effect, control, true);
300 break; 987 break;
301 case IrOpcode::kChangeTaggedToUint32: 988 case IrOpcode::kChangeTaggedToUint32:
302 DoChangeTaggedToUI32(node, start, start, false); 989 DoChangeTaggedToUI32(node, effect, control, false);
303 break; 990 break;
304 case IrOpcode::kChangeTaggedToFloat64: 991 case IrOpcode::kChangeTaggedToFloat64:
305 DoChangeTaggedToFloat64(node, start, start); 992 DoChangeTaggedToFloat64(node, effect, control);
306 break; 993 break;
307 case IrOpcode::kChangeInt32ToTagged: 994 case IrOpcode::kChangeInt32ToTagged:
308 DoChangeUI32ToTagged(node, start, start, true); 995 DoChangeUI32ToTagged(node, effect, control, true);
309 break; 996 break;
310 case IrOpcode::kChangeUint32ToTagged: 997 case IrOpcode::kChangeUint32ToTagged:
311 DoChangeUI32ToTagged(node, start, start, false); 998 DoChangeUI32ToTagged(node, effect, control, false);
312 break; 999 break;
313 case IrOpcode::kChangeFloat64ToTagged: 1000 case IrOpcode::kChangeFloat64ToTagged:
314 DoChangeFloat64ToTagged(node, start, start); 1001 DoChangeFloat64ToTagged(node, effect, control);
315 break; 1002 break;
316 case IrOpcode::kChangeBoolToBit: 1003 case IrOpcode::kChangeBoolToBit:
317 DoChangeBoolToBit(node, start, start); 1004 DoChangeBoolToBit(node, effect, control);
318 break; 1005 break;
319 case IrOpcode::kChangeBitToBool: 1006 case IrOpcode::kChangeBitToBool:
320 DoChangeBitToBool(node, start, start); 1007 DoChangeBitToBool(node, effect, control);
321 break;
322 case IrOpcode::kLoadField:
323 DoLoadField(node, start, start);
324 break;
325 case IrOpcode::kStoreField:
326 DoStoreField(node, start, start);
327 break;
328 case IrOpcode::kLoadElement:
329 DoLoadElement(node, start, start);
330 break;
331 case IrOpcode::kStoreElement:
332 DoStoreElement(node, start, start);
333 break; 1008 break;
334 default: 1009 default:
1010 UNREACHABLE();
335 break; 1011 break;
336 } 1012 }
337 } 1013 }
338 1014
339 } // namespace compiler 1015 } // namespace compiler
340 } // namespace internal 1016 } // namespace internal
341 } // namespace v8 1017 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698