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 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 void VisitInt64Binop(Node* node) { VisitBinop(node, kMachInt64, kMachInt64); } | 289 void VisitInt64Binop(Node* node) { VisitBinop(node, kMachInt64, kMachInt64); } |
290 void VisitUint64Binop(Node* node) { | 290 void VisitUint64Binop(Node* node) { |
291 VisitBinop(node, kMachUint64, kMachUint64); | 291 VisitBinop(node, kMachUint64, kMachUint64); |
292 } | 292 } |
293 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } | 293 void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); } |
294 void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } | 294 void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); } |
295 void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } | 295 void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); } |
296 void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } | 296 void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); } |
297 void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } | 297 void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); } |
298 | 298 |
| 299 // Infer representation for phi-like nodes. |
| 300 MachineType GetRepresentationForPhi(Node* node, MachineTypeUnion use) { |
| 301 // Phis adapt to the output representation their uses demand. |
| 302 Type* upper = NodeProperties::GetBounds(node).upper; |
| 303 if ((use & kRepMask) == kRepTagged) { |
| 304 // only tagged uses. |
| 305 return kRepTagged; |
| 306 } else if (IsSafeIntAdditiveOperand(node)) { |
| 307 // Integer within [-2^52, 2^52] range. |
| 308 if ((use & kRepMask) == kRepFloat64) { |
| 309 // only float64 uses. |
| 310 return kRepFloat64; |
| 311 } else if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { |
| 312 // multiple uses, but we are within 32 bits range => pick kRepWord32. |
| 313 return kRepWord32; |
| 314 } else if ((use & kRepMask) == kRepWord32 || |
| 315 (use & kTypeMask) == kTypeInt32 || |
| 316 (use & kTypeMask) == kTypeUint32) { |
| 317 // The type is a safe integer, but we only use 32 bits. |
| 318 return kRepWord32; |
| 319 } else { |
| 320 return kRepFloat64; |
| 321 } |
| 322 } else if (upper->Is(Type::Boolean())) { |
| 323 // multiple uses => pick kRepBit. |
| 324 return kRepBit; |
| 325 } else if (upper->Is(Type::Number())) { |
| 326 // multiple uses => pick kRepFloat64. |
| 327 return kRepFloat64; |
| 328 } |
| 329 return kRepTagged; |
| 330 } |
| 331 |
299 // Helper for handling selects. | 332 // Helper for handling selects. |
300 // TODO(turbofan): Share some code with VisitPhi() below? | |
301 void VisitSelect(Node* node, MachineTypeUnion use, | 333 void VisitSelect(Node* node, MachineTypeUnion use, |
302 SimplifiedLowering* lowering) { | 334 SimplifiedLowering* lowering) { |
303 ProcessInput(node, 0, kRepBit); | 335 ProcessInput(node, 0, kRepBit); |
| 336 MachineType output = GetRepresentationForPhi(node, use); |
304 | 337 |
305 // Selects adapt to the output representation their uses demand, pushing | |
306 // representation changes to their inputs. | |
307 Type* upper = NodeProperties::GetBounds(node).upper; | 338 Type* upper = NodeProperties::GetBounds(node).upper; |
308 MachineType output = kMachNone; | |
309 MachineType propagate = kMachNone; | |
310 | |
311 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { | |
312 // legal = kRepTagged | kRepFloat64 | kRepWord32; | |
313 if ((use & kRepMask) == kRepTagged) { | |
314 // only tagged uses. | |
315 output = kRepTagged; | |
316 propagate = kRepTagged; | |
317 } else if ((use & kRepMask) == kRepFloat64) { | |
318 // only float64 uses. | |
319 output = kRepFloat64; | |
320 propagate = kRepFloat64; | |
321 } else { | |
322 // multiple uses. | |
323 output = kRepWord32; | |
324 propagate = kRepWord32; | |
325 } | |
326 } else if (upper->Is(Type::Boolean())) { | |
327 // legal = kRepTagged | kRepBit; | |
328 if ((use & kRepMask) == kRepTagged) { | |
329 // only tagged uses. | |
330 output = kRepTagged; | |
331 propagate = kRepTagged; | |
332 } else { | |
333 // multiple uses. | |
334 output = kRepBit; | |
335 propagate = kRepBit; | |
336 } | |
337 } else if (upper->Is(Type::Number())) { | |
338 // legal = kRepTagged | kRepFloat64; | |
339 if ((use & kRepMask) == kRepTagged) { | |
340 // only tagged uses. | |
341 output = kRepTagged; | |
342 propagate = kRepTagged; | |
343 } else { | |
344 // multiple uses. | |
345 output = kRepFloat64; | |
346 propagate = kRepFloat64; | |
347 } | |
348 } else { | |
349 // legal = kRepTagged; | |
350 output = kRepTagged; | |
351 propagate = kRepTagged; | |
352 } | |
353 | |
354 MachineType output_type = | 339 MachineType output_type = |
355 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 340 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
356 SetOutput(node, output_type); | 341 SetOutput(node, output_type); |
357 | 342 |
358 if (lower()) { | 343 if (lower()) { |
359 // Update the select operator. | 344 // Update the select operator. |
360 SelectParameters p = SelectParametersOf(node->op()); | 345 SelectParameters p = SelectParametersOf(node->op()); |
361 MachineType type = static_cast<MachineType>(output_type); | 346 MachineType type = static_cast<MachineType>(output_type); |
362 if (type != p.type()) { | 347 if (type != p.type()) { |
363 node->set_op(lowering->common()->Select(type, p.hint())); | 348 node->set_op(lowering->common()->Select(type, p.hint())); |
364 } | 349 } |
365 | 350 |
366 // Convert inputs to the output representation of this select. | 351 // Convert inputs to the output representation of this select. |
367 ProcessInput(node, 1, output_type); | 352 ProcessInput(node, 1, output_type); |
368 ProcessInput(node, 2, output_type); | 353 ProcessInput(node, 2, output_type); |
369 } else { | 354 } else { |
370 // Propagate {use} of the select to value inputs. | 355 // Propagate {use} of the select to value inputs. |
371 MachineType use_type = | 356 MachineType use_type = |
372 static_cast<MachineType>((use & kTypeMask) | propagate); | 357 static_cast<MachineType>((use & kTypeMask) | output); |
373 ProcessInput(node, 1, use_type); | 358 ProcessInput(node, 1, use_type); |
374 ProcessInput(node, 2, use_type); | 359 ProcessInput(node, 2, use_type); |
375 } | 360 } |
376 } | 361 } |
377 | 362 |
378 // Helper for handling phis. | 363 // Helper for handling phis. |
379 void VisitPhi(Node* node, MachineTypeUnion use, | 364 void VisitPhi(Node* node, MachineTypeUnion use, |
380 SimplifiedLowering* lowering) { | 365 SimplifiedLowering* lowering) { |
381 // Phis adapt to the output representation their uses demand, pushing | 366 MachineType output = GetRepresentationForPhi(node, use); |
382 // representation changes to their inputs. | 367 |
383 Type* upper = NodeProperties::GetBounds(node).upper; | 368 Type* upper = NodeProperties::GetBounds(node).upper; |
384 MachineType output = kMachNone; | |
385 MachineType propagate = kMachNone; | |
386 | |
387 if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) { | |
388 // legal = kRepTagged | kRepFloat64 | kRepWord32; | |
389 if ((use & kRepMask) == kRepTagged) { | |
390 // only tagged uses. | |
391 output = kRepTagged; | |
392 propagate = kRepTagged; | |
393 } else if ((use & kRepMask) == kRepFloat64) { | |
394 // only float64 uses. | |
395 output = kRepFloat64; | |
396 propagate = kRepFloat64; | |
397 } else { | |
398 // multiple uses. | |
399 output = kRepWord32; | |
400 propagate = kRepWord32; | |
401 } | |
402 } else if (upper->Is(Type::Boolean())) { | |
403 // legal = kRepTagged | kRepBit; | |
404 if ((use & kRepMask) == kRepTagged) { | |
405 // only tagged uses. | |
406 output = kRepTagged; | |
407 propagate = kRepTagged; | |
408 } else { | |
409 // multiple uses. | |
410 output = kRepBit; | |
411 propagate = kRepBit; | |
412 } | |
413 } else if (upper->Is(Type::Number())) { | |
414 // legal = kRepTagged | kRepFloat64; | |
415 if ((use & kRepMask) == kRepTagged) { | |
416 // only tagged uses. | |
417 output = kRepTagged; | |
418 propagate = kRepTagged; | |
419 } else { | |
420 // multiple uses. | |
421 output = kRepFloat64; | |
422 propagate = kRepFloat64; | |
423 } | |
424 } else { | |
425 // legal = kRepTagged; | |
426 output = kRepTagged; | |
427 propagate = kRepTagged; | |
428 } | |
429 | |
430 MachineType output_type = | 369 MachineType output_type = |
431 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); | 370 static_cast<MachineType>(changer_->TypeFromUpperBound(upper) | output); |
432 SetOutput(node, output_type); | 371 SetOutput(node, output_type); |
433 | 372 |
434 int values = node->op()->ValueInputCount(); | 373 int values = node->op()->ValueInputCount(); |
435 | 374 |
436 if (lower()) { | 375 if (lower()) { |
437 // Update the phi operator. | 376 // Update the phi operator. |
438 MachineType type = static_cast<MachineType>(output_type); | 377 MachineType type = static_cast<MachineType>(output_type); |
439 if (type != OpParameter<MachineType>(node)) { | 378 if (type != OpParameter<MachineType>(node)) { |
440 node->set_op(lowering->common()->Phi(type, values)); | 379 node->set_op(lowering->common()->Phi(type, values)); |
441 } | 380 } |
442 | 381 |
443 // Convert inputs to the output representation of this phi. | 382 // Convert inputs to the output representation of this phi. |
444 Node::Inputs inputs = node->inputs(); | 383 Node::Inputs inputs = node->inputs(); |
445 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); | 384 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); |
446 ++iter, --values) { | 385 ++iter, --values) { |
447 // TODO(titzer): it'd be nice to have distinguished edge kinds here. | 386 // TODO(titzer): it'd be nice to have distinguished edge kinds here. |
448 ProcessInput(node, iter.index(), values > 0 ? output_type : 0); | 387 ProcessInput(node, iter.index(), values > 0 ? output_type : 0); |
449 } | 388 } |
450 } else { | 389 } else { |
451 // Propagate {use} of the phi to value inputs, and 0 to control. | 390 // Propagate {use} of the phi to value inputs, and 0 to control. |
452 Node::Inputs inputs = node->inputs(); | 391 Node::Inputs inputs = node->inputs(); |
453 MachineType use_type = | 392 MachineType use_type = |
454 static_cast<MachineType>((use & kTypeMask) | propagate); | 393 static_cast<MachineType>((use & kTypeMask) | output); |
455 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); | 394 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); |
456 ++iter, --values) { | 395 ++iter, --values) { |
457 // TODO(titzer): it'd be nice to have distinguished edge kinds here. | 396 // TODO(titzer): it'd be nice to have distinguished edge kinds here. |
458 ProcessInput(node, iter.index(), values > 0 ? use_type : 0); | 397 ProcessInput(node, iter.index(), values > 0 ? use_type : 0); |
459 } | 398 } |
460 } | 399 } |
461 } | 400 } |
462 | 401 |
463 const Operator* Int32Op(Node* node) { | 402 const Operator* Int32Op(Node* node) { |
464 return changer_->Int32OperatorFor(node->opcode()); | 403 return changer_->Int32OperatorFor(node->opcode()); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 break; | 657 break; |
719 } | 658 } |
720 // => Float64Mod | 659 // => Float64Mod |
721 VisitFloat64Binop(node); | 660 VisitFloat64Binop(node); |
722 if (lower()) node->set_op(Float64Op(node)); | 661 if (lower()) node->set_op(Float64Op(node)); |
723 break; | 662 break; |
724 } | 663 } |
725 case IrOpcode::kNumberToInt32: { | 664 case IrOpcode::kNumberToInt32: { |
726 MachineTypeUnion use_rep = use & kRepMask; | 665 MachineTypeUnion use_rep = use & kRepMask; |
727 Node* input = node->InputAt(0); | 666 Node* input = node->InputAt(0); |
| 667 Type* in_upper = NodeProperties::GetBounds(input).upper; |
728 MachineTypeUnion in = GetInfo(input)->output; | 668 MachineTypeUnion in = GetInfo(input)->output; |
729 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) { | 669 if (in_upper->Is(Type::Signed32())) { |
730 // If the input has type int32, pass through representation. | 670 // If the input has type int32, pass through representation. |
731 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); | 671 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); |
732 if (lower()) DeferReplacement(node, node->InputAt(0)); | 672 if (lower()) DeferReplacement(node, node->InputAt(0)); |
733 } else if ((in & kTypeMask) == kTypeUint32 || | 673 } else if ((in & kTypeMask) == kTypeUint32 || |
734 (in & kTypeMask) == kTypeInt32 || | 674 (in & kTypeMask) == kTypeInt32 || |
| 675 in_upper->Is(Type::Unsigned32()) || |
735 (in & kRepMask) == kRepWord32) { | 676 (in & kRepMask) == kRepWord32) { |
736 // Just change representation if necessary. | 677 // Just change representation if necessary. |
737 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); | 678 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); |
738 if (lower()) DeferReplacement(node, node->InputAt(0)); | 679 if (lower()) DeferReplacement(node, node->InputAt(0)); |
739 } else { | 680 } else { |
740 // Require the input in float64 format and perform truncation. | 681 // Require the input in float64 format and perform truncation. |
741 // TODO(turbofan): avoid a truncation with a smi check. | 682 // TODO(turbofan): avoid a truncation with a smi check. |
742 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); | 683 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); |
743 if (lower()) | 684 if (lower()) |
744 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); | 685 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); |
745 } | 686 } |
746 break; | 687 break; |
747 } | 688 } |
748 case IrOpcode::kNumberToUint32: { | 689 case IrOpcode::kNumberToUint32: { |
749 MachineTypeUnion use_rep = use & kRepMask; | 690 MachineTypeUnion use_rep = use & kRepMask; |
750 Node* input = node->InputAt(0); | 691 Node* input = node->InputAt(0); |
| 692 Type* in_upper = NodeProperties::GetBounds(input).upper; |
751 MachineTypeUnion in = GetInfo(input)->output; | 693 MachineTypeUnion in = GetInfo(input)->output; |
752 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) { | 694 if (in_upper->Is(Type::Unsigned32())) { |
753 // If the input has type uint32, pass through representation. | 695 // If the input has type uint32, pass through representation. |
754 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); | 696 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); |
755 if (lower()) DeferReplacement(node, node->InputAt(0)); | 697 if (lower()) DeferReplacement(node, node->InputAt(0)); |
756 } else if ((in & kTypeMask) == kTypeUint32 || | 698 } else if ((in & kTypeMask) == kTypeUint32 || |
757 (in & kTypeMask) == kTypeInt32 || | 699 (in & kTypeMask) == kTypeInt32 || |
| 700 in_upper->Is(Type::Signed32()) || |
758 (in & kRepMask) == kRepWord32) { | 701 (in & kRepMask) == kRepWord32) { |
759 // Just change representation if necessary. | 702 // Just change representation if necessary. |
760 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); | 703 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); |
761 if (lower()) DeferReplacement(node, node->InputAt(0)); | 704 if (lower()) DeferReplacement(node, node->InputAt(0)); |
762 } else { | 705 } else { |
763 // Require the input in float64 format and perform truncation. | 706 // Require the input in float64 format and perform truncation. |
764 // TODO(turbofan): avoid a truncation with a smi check. | 707 // TODO(turbofan): avoid a truncation with a smi check. |
765 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); | 708 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); |
766 if (lower()) | 709 if (lower()) |
767 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); | 710 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1524 | 1467 |
1525 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1468 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
1526 node->set_op(machine()->IntLessThanOrEqual()); | 1469 node->set_op(machine()->IntLessThanOrEqual()); |
1527 node->ReplaceInput(0, StringComparison(node, true)); | 1470 node->ReplaceInput(0, StringComparison(node, true)); |
1528 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1471 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
1529 } | 1472 } |
1530 | 1473 |
1531 } // namespace compiler | 1474 } // namespace compiler |
1532 } // namespace internal | 1475 } // namespace internal |
1533 } // namespace v8 | 1476 } // namespace v8 |
OLD | NEW |