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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 type = Type::Any(); | 493 type = Type::Any(); |
494 break; | 494 break; |
495 } | 495 } |
496 return SetOutput(node, NodeOutputInfo(machine_type.representation(), type)); | 496 return SetOutput(node, NodeOutputInfo(machine_type.representation(), type)); |
497 } | 497 } |
498 | 498 |
499 void SetOutput(Node* node, NodeOutputInfo output_info) { | 499 void SetOutput(Node* node, NodeOutputInfo output_info) { |
500 // Every node should have at most one output representation. Note that | 500 // Every node should have at most one output representation. Note that |
501 // phis can have 0, if they have not been used in a representation-inducing | 501 // phis can have 0, if they have not been used in a representation-inducing |
502 // instruction. | 502 // instruction. |
| 503 Type* output_type = output_info.type(); |
| 504 if (NodeProperties::IsTyped(node)) { |
| 505 output_type = Type::Intersect(NodeProperties::GetType(node), |
| 506 output_info.type(), jsgraph_->zone()); |
| 507 } |
503 NodeInfo* info = GetInfo(node); | 508 NodeInfo* info = GetInfo(node); |
| 509 DCHECK(info->output_type()->Is(output_type)); |
504 DCHECK(MachineRepresentationIsSubtype(info->representation(), | 510 DCHECK(MachineRepresentationIsSubtype(info->representation(), |
505 output_info.representation())); | 511 output_info.representation())); |
506 DCHECK(info->output_type()->Is(output_info.type())); | 512 if (!output_type->Is(info->output_type()) || |
507 if (!output_info.type()->Is(info->output_type()) || | |
508 output_info.representation() != info->representation()) { | 513 output_info.representation() != info->representation()) { |
509 EnqueueUses(node); | 514 EnqueueUses(node); |
510 } | 515 } |
511 info->set_output_type(output_info); | 516 info->set_output_type( |
| 517 NodeOutputInfo(output_info.representation(), output_type)); |
512 } | 518 } |
513 | 519 |
514 bool BothInputsAreSigned32(Node* node) { | 520 bool BothInputsAreSigned32(Node* node) { |
515 DCHECK_EQ(2, node->InputCount()); | 521 DCHECK_EQ(2, node->InputCount()); |
516 return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Signed32()) || | 522 return GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32()) && |
517 GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32())) && | 523 GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32()); |
518 (NodeProperties::GetType(node->InputAt(1))->Is(Type::Signed32()) || | |
519 GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32())); | |
520 } | 524 } |
521 | 525 |
522 bool BothInputsAreUnsigned32(Node* node) { | 526 bool BothInputsAreUnsigned32(Node* node) { |
523 DCHECK_EQ(2, node->InputCount()); | 527 DCHECK_EQ(2, node->InputCount()); |
524 return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Unsigned32()) || | 528 return GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32()) && |
525 GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32())) && | 529 GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32()); |
526 (NodeProperties::GetType(node->InputAt(1))->Is(Type::Unsigned32()) || | |
527 GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32())); | |
528 } | 530 } |
529 | 531 |
530 bool BothInputsAre(Node* node, Type* type) { | 532 bool BothInputsAre(Node* node, Type* type) { |
531 DCHECK_EQ(2, node->InputCount()); | 533 DCHECK_EQ(2, node->InputCount()); |
532 return NodeProperties::GetType(node->InputAt(0))->Is(type) && | 534 return GetInfo(node->InputAt(0))->output_type()->Is(type) && |
533 NodeProperties::GetType(node->InputAt(1))->Is(type); | 535 GetInfo(node->InputAt(1))->output_type()->Is(type); |
534 } | 536 } |
535 | 537 |
536 void ConvertInput(Node* node, int index, UseInfo use) { | 538 void ConvertInput(Node* node, int index, UseInfo use) { |
537 Node* input = node->InputAt(index); | 539 Node* input = node->InputAt(index); |
538 // In the change phase, insert a change before the use if necessary. | 540 // In the change phase, insert a change before the use if necessary. |
539 if (use.preferred() == MachineRepresentation::kNone) | 541 if (use.preferred() == MachineRepresentation::kNone) |
540 return; // No input requirement on the use. | 542 return; // No input requirement on the use. |
541 NodeInfo* input_info = GetInfo(input); | 543 NodeInfo* input_info = GetInfo(input); |
542 MachineRepresentation input_rep = input_info->representation(); | 544 MachineRepresentation input_rep = input_info->representation(); |
543 if (input_rep != use.preferred()) { | 545 if (input_rep != use.preferred()) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool()); | 656 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool()); |
655 } | 657 } |
656 void VisitInt64Cmp(Node* node) { | 658 void VisitInt64Cmp(Node* node) { |
657 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool()); | 659 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool()); |
658 } | 660 } |
659 void VisitUint64Cmp(Node* node) { | 661 void VisitUint64Cmp(Node* node) { |
660 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool()); | 662 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool()); |
661 } | 663 } |
662 | 664 |
663 // Infer representation for phi-like nodes. | 665 // Infer representation for phi-like nodes. |
664 static MachineRepresentation GetRepresentationForPhi(Node* node, | 666 NodeOutputInfo GetOutputInfoForPhi(Node* node, Truncation use) { |
665 Truncation use) { | 667 // Compute the type. |
666 // Phis adapt to the output representation their uses demand. | 668 Type* type = GetInfo(node->InputAt(0))->output_type(); |
667 Type* type = NodeProperties::GetType(node); | 669 for (int i = 1; i < node->op()->ValueInputCount(); ++i) { |
668 if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { | 670 type = Type::Union(type, GetInfo(node->InputAt(i))->output_type(), |
669 // We are within 32 bits range => pick kRepWord32. | 671 jsgraph_->zone()); |
670 return MachineRepresentation::kWord32; | 672 } |
| 673 |
| 674 // Compute the representation. |
| 675 MachineRepresentation rep = MachineRepresentation::kTagged; |
| 676 if (type->Is(Type::None())) { |
| 677 rep = MachineRepresentation::kNone; |
| 678 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { |
| 679 rep = MachineRepresentation::kWord32; |
671 } else if (use.TruncatesToWord32()) { | 680 } else if (use.TruncatesToWord32()) { |
672 // We only use 32 bits. | 681 rep = MachineRepresentation::kWord32; |
673 return MachineRepresentation::kWord32; | |
674 } else if (type->Is(Type::Boolean())) { | 682 } else if (type->Is(Type::Boolean())) { |
675 // multiple uses => pick kRepBit. | 683 rep = MachineRepresentation::kBit; |
676 return MachineRepresentation::kBit; | |
677 } else if (type->Is(Type::Number())) { | 684 } else if (type->Is(Type::Number())) { |
678 // multiple uses => pick kRepFloat64. | 685 rep = MachineRepresentation::kFloat64; |
679 return MachineRepresentation::kFloat64; | |
680 } else if (type->Is(Type::Internal())) { | 686 } else if (type->Is(Type::Internal())) { |
681 return MachineType::PointerRepresentation(); | 687 // We mark (u)int64 as Type::Internal. |
| 688 // TODO(jarin) This is a workaround for our lack of (u)int64 |
| 689 // types. This can be removed once we can represent (u)int64 |
| 690 // unambiguously. (At the moment internal objects, such as the hole, |
| 691 // are also Type::Internal()). |
| 692 bool is_word64 = GetInfo(node->InputAt(0))->representation() == |
| 693 MachineRepresentation::kWord64; |
| 694 #ifdef DEBUG |
| 695 // Check that all the inputs agree on being Word64. |
| 696 for (int i = 1; i < node->op()->ValueInputCount(); i++) { |
| 697 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() == |
| 698 MachineRepresentation::kWord64); |
| 699 } |
| 700 #endif |
| 701 rep = is_word64 ? MachineRepresentation::kWord64 |
| 702 : MachineRepresentation::kTagged; |
682 } | 703 } |
683 return MachineRepresentation::kTagged; | 704 return NodeOutputInfo(rep, type); |
684 } | 705 } |
685 | 706 |
686 // Helper for handling selects. | 707 // Helper for handling selects. |
687 void VisitSelect(Node* node, Truncation truncation, | 708 void VisitSelect(Node* node, Truncation truncation, |
688 SimplifiedLowering* lowering) { | 709 SimplifiedLowering* lowering) { |
689 ProcessInput(node, 0, UseInfo::Bool()); | 710 ProcessInput(node, 0, UseInfo::Bool()); |
690 MachineRepresentation output = GetRepresentationForPhi(node, truncation); | |
691 | 711 |
692 Type* type = NodeProperties::GetType(node); | 712 NodeOutputInfo output = GetOutputInfoForPhi(node, truncation); |
693 SetOutput(node, NodeOutputInfo(output, type)); | 713 SetOutput(node, output); |
694 | 714 |
695 if (lower()) { | 715 if (lower()) { |
696 // Update the select operator. | 716 // Update the select operator. |
697 SelectParameters p = SelectParametersOf(node->op()); | 717 SelectParameters p = SelectParametersOf(node->op()); |
698 if (output != p.representation()) { | 718 if (output.representation() != p.representation()) { |
699 NodeProperties::ChangeOp(node, | 719 NodeProperties::ChangeOp(node, lowering->common()->Select( |
700 lowering->common()->Select(output, p.hint())); | 720 output.representation(), p.hint())); |
701 } | 721 } |
702 } | 722 } |
703 // Convert inputs to the output representation of this phi, pass the | 723 // Convert inputs to the output representation of this phi, pass the |
704 // truncation truncation along. | 724 // truncation truncation along. |
705 UseInfo input_use(output, truncation); | 725 UseInfo input_use(output.representation(), truncation); |
706 ProcessInput(node, 1, input_use); | 726 ProcessInput(node, 1, input_use); |
707 ProcessInput(node, 2, input_use); | 727 ProcessInput(node, 2, input_use); |
708 } | 728 } |
709 | 729 |
710 // Helper for handling phis. | 730 // Helper for handling phis. |
711 void VisitPhi(Node* node, Truncation truncation, | 731 void VisitPhi(Node* node, Truncation truncation, |
712 SimplifiedLowering* lowering) { | 732 SimplifiedLowering* lowering) { |
713 MachineRepresentation output = GetRepresentationForPhi(node, truncation); | 733 NodeOutputInfo output = GetOutputInfoForPhi(node, truncation); |
714 | 734 SetOutput(node, output); |
715 Type* type = NodeProperties::GetType(node); | |
716 SetOutput(node, NodeOutputInfo(output, type)); | |
717 | 735 |
718 int values = node->op()->ValueInputCount(); | 736 int values = node->op()->ValueInputCount(); |
719 | |
720 if (lower()) { | 737 if (lower()) { |
721 // Update the phi operator. | 738 // Update the phi operator. |
722 if (output != PhiRepresentationOf(node->op())) { | 739 if (output.representation() != PhiRepresentationOf(node->op())) { |
723 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values)); | 740 NodeProperties::ChangeOp( |
| 741 node, lowering->common()->Phi(output.representation(), values)); |
724 } | 742 } |
725 } | 743 } |
726 | 744 |
727 // Convert inputs to the output representation of this phi, pass the | 745 // Convert inputs to the output representation of this phi, pass the |
728 // truncation truncation along. | 746 // truncation truncation along. |
729 UseInfo input_use(output, truncation); | 747 UseInfo input_use(output.representation(), truncation); |
730 for (int i = 0; i < node->InputCount(); i++) { | 748 for (int i = 0; i < node->InputCount(); i++) { |
731 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); | 749 ProcessInput(node, i, i < values ? input_use : UseInfo::None()); |
732 } | 750 } |
733 } | 751 } |
734 | 752 |
735 void VisitCall(Node* node, SimplifiedLowering* lowering) { | 753 void VisitCall(Node* node, SimplifiedLowering* lowering) { |
736 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); | 754 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op()); |
737 const MachineSignature* sig = desc->GetMachineSignature(); | 755 const MachineSignature* sig = desc->GetMachineSignature(); |
738 int params = static_cast<int>(sig->parameter_count()); | 756 int params = static_cast<int>(sig->parameter_count()); |
739 // Propagate representation information from call descriptor. | 757 // Propagate representation information from call descriptor. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 for (int i = 0; i < node->InputCount(); i++) { | 791 for (int i = 0; i < node->InputCount(); i++) { |
774 EnqueueInput(node, i, UseInfo::Any()); | 792 EnqueueInput(node, i, UseInfo::Any()); |
775 } | 793 } |
776 } else { | 794 } else { |
777 Zone* zone = jsgraph_->zone(); | 795 Zone* zone = jsgraph_->zone(); |
778 ZoneVector<MachineType>* types = | 796 ZoneVector<MachineType>* types = |
779 new (zone->New(sizeof(ZoneVector<MachineType>))) | 797 new (zone->New(sizeof(ZoneVector<MachineType>))) |
780 ZoneVector<MachineType>(node->InputCount(), zone); | 798 ZoneVector<MachineType>(node->InputCount(), zone); |
781 for (int i = 0; i < node->InputCount(); i++) { | 799 for (int i = 0; i < node->InputCount(); i++) { |
782 NodeInfo* input_info = GetInfo(node->InputAt(i)); | 800 NodeInfo* input_info = GetInfo(node->InputAt(i)); |
783 (*types)[i] = | 801 MachineType machine_type( |
784 MachineType(input_info->representation(), | 802 input_info->representation(), |
785 DeoptValueSemanticOf(input_info->output_type())); | 803 DeoptValueSemanticOf(input_info->output_type())); |
| 804 DCHECK(machine_type.representation() != |
| 805 MachineRepresentation::kWord32 || |
| 806 machine_type.semantic() == MachineSemantic::kInt32 || |
| 807 machine_type.semantic() == MachineSemantic::kUint32); |
| 808 (*types)[i] = machine_type; |
786 } | 809 } |
787 NodeProperties::ChangeOp(node, | 810 NodeProperties::ChangeOp(node, |
788 jsgraph_->common()->TypedStateValues(types)); | 811 jsgraph_->common()->TypedStateValues(types)); |
789 } | 812 } |
790 SetOutput(node, NodeOutputInfo::AnyTagged()); | 813 SetOutput(node, NodeOutputInfo::AnyTagged()); |
791 } | 814 } |
792 | 815 |
793 const Operator* Int32Op(Node* node) { | 816 const Operator* Int32Op(Node* node) { |
794 return changer_->Int32OperatorFor(node->opcode()); | 817 return changer_->Int32OperatorFor(node->opcode()); |
795 } | 818 } |
796 | 819 |
797 const Operator* Uint32Op(Node* node) { | 820 const Operator* Uint32Op(Node* node) { |
798 return changer_->Uint32OperatorFor(node->opcode()); | 821 return changer_->Uint32OperatorFor(node->opcode()); |
799 } | 822 } |
800 | 823 |
801 const Operator* Float64Op(Node* node) { | 824 const Operator* Float64Op(Node* node) { |
802 return changer_->Float64OperatorFor(node->opcode()); | 825 return changer_->Float64OperatorFor(node->opcode()); |
803 } | 826 } |
804 | 827 |
805 bool CanLowerToInt32Binop(Node* node, Truncation use) { | |
806 return BothInputsAreSigned32(node) && | |
807 NodeProperties::GetType(node)->Is(Type::Signed32()); | |
808 } | |
809 | |
810 bool CanLowerToInt32AdditiveBinop(Node* node, Truncation use) { | |
811 // It is safe to lower to word32 operation if: | |
812 // - the inputs are safe integers (so the low bits are not discarded), and | |
813 // - the uses can only observe the lowest 32 bits. | |
814 // TODO(jarin): we could support the uint32 case here, but that would | |
815 // require setting kTypeUint32 as the output type. Eventually, we will want | |
816 // to use only the big types, then this should work automatically. | |
817 return BothInputsAre(node, type_cache_.kAdditiveSafeInteger) && | |
818 use.TruncatesToWord32(); | |
819 } | |
820 | |
821 bool CanLowerToInt32MultiplicativeBinop(Node* node, Truncation use) { | |
822 return BothInputsAreSigned32(node) && use.TruncatesToWord32() && | |
823 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger); | |
824 } | |
825 | |
826 // Dispatching routine for visiting the node {node} with the usage {use}. | 828 // Dispatching routine for visiting the node {node} with the usage {use}. |
827 // Depending on the operator, propagate new usage info to the inputs. | 829 // Depending on the operator, propagate new usage info to the inputs. |
828 void VisitNode(Node* node, Truncation truncation, | 830 void VisitNode(Node* node, Truncation truncation, |
829 SimplifiedLowering* lowering) { | 831 SimplifiedLowering* lowering) { |
830 switch (node->opcode()) { | 832 switch (node->opcode()) { |
831 //------------------------------------------------------------------ | 833 //------------------------------------------------------------------ |
832 // Common operators. | 834 // Common operators. |
833 //------------------------------------------------------------------ | 835 //------------------------------------------------------------------ |
834 case IrOpcode::kStart: | 836 case IrOpcode::kStart: |
835 case IrOpcode::kDead: | 837 case IrOpcode::kDead: |
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1919 ReplaceEffectUses(node, comparison); | 1921 ReplaceEffectUses(node, comparison); |
1920 node->ReplaceInput(0, comparison); | 1922 node->ReplaceInput(0, comparison); |
1921 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1923 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
1922 node->TrimInputCount(2); | 1924 node->TrimInputCount(2); |
1923 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); | 1925 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); |
1924 } | 1926 } |
1925 | 1927 |
1926 } // namespace compiler | 1928 } // namespace compiler |
1927 } // namespace internal | 1929 } // namespace internal |
1928 } // namespace v8 | 1930 } // namespace v8 |
OLD | NEW |