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 #ifndef V8_COMPILER_INSTRUCTION_H_ | 5 #ifndef V8_COMPILER_INSTRUCTION_H_ |
6 #define V8_COMPILER_INSTRUCTION_H_ | 6 #define V8_COMPILER_INSTRUCTION_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <iosfwd> | 9 #include <iosfwd> |
10 #include <map> | 10 #include <map> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "src/register-configuration.h" | 21 #include "src/register-configuration.h" |
22 #include "src/zone/zone-allocator.h" | 22 #include "src/zone/zone-allocator.h" |
23 | 23 |
24 namespace v8 { | 24 namespace v8 { |
25 namespace internal { | 25 namespace internal { |
26 namespace compiler { | 26 namespace compiler { |
27 | 27 |
28 // Forward declarations. | 28 // Forward declarations. |
29 class Schedule; | 29 class Schedule; |
30 | 30 |
31 | 31 class V8_EXPORT_PRIVATE InstructionOperand { |
32 class InstructionOperand { | |
33 public: | 32 public: |
34 static const int kInvalidVirtualRegister = -1; | 33 static const int kInvalidVirtualRegister = -1; |
35 | 34 |
36 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with | 35 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with |
37 // kInvalidVirtualRegister and some DCHECKS. | 36 // kInvalidVirtualRegister and some DCHECKS. |
38 enum Kind { | 37 enum Kind { |
39 INVALID, | 38 INVALID, |
40 UNALLOCATED, | 39 UNALLOCATED, |
41 CONSTANT, | 40 CONSTANT, |
42 IMMEDIATE, | 41 IMMEDIATE, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 } | 111 } |
113 | 112 |
114 bool EqualsCanonicalized(const InstructionOperand& that) const { | 113 bool EqualsCanonicalized(const InstructionOperand& that) const { |
115 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue(); | 114 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue(); |
116 } | 115 } |
117 | 116 |
118 bool CompareCanonicalized(const InstructionOperand& that) const { | 117 bool CompareCanonicalized(const InstructionOperand& that) const { |
119 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue(); | 118 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue(); |
120 } | 119 } |
121 | 120 |
122 bool InterferesWith(const InstructionOperand& that) const; | 121 bool InterferesWith(const InstructionOperand& other) const; |
123 | 122 |
124 // APIs to aid debugging. For general-stream APIs, use operator<< | 123 // APIs to aid debugging. For general-stream APIs, use operator<< |
125 void Print(const RegisterConfiguration* config) const; | 124 void Print(const RegisterConfiguration* config) const; |
126 void Print() const; | 125 void Print() const; |
127 | 126 |
128 protected: | 127 protected: |
129 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {} | 128 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {} |
130 | 129 |
131 inline uint64_t GetCanonicalizedValue() const; | 130 inline uint64_t GetCanonicalizedValue() const; |
132 | 131 |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 LocationOperand::cast(this)->location_kind() == | 633 LocationOperand::cast(this)->location_kind() == |
635 LocationOperand::STACK_SLOT && | 634 LocationOperand::STACK_SLOT && |
636 LocationOperand::cast(this)->representation() == | 635 LocationOperand::cast(this)->representation() == |
637 MachineRepresentation::kSimd128; | 636 MachineRepresentation::kSimd128; |
638 } | 637 } |
639 | 638 |
640 uint64_t InstructionOperand::GetCanonicalizedValue() const { | 639 uint64_t InstructionOperand::GetCanonicalizedValue() const { |
641 if (IsAnyLocationOperand()) { | 640 if (IsAnyLocationOperand()) { |
642 MachineRepresentation canonical = MachineRepresentation::kNone; | 641 MachineRepresentation canonical = MachineRepresentation::kNone; |
643 if (IsFPRegister()) { | 642 if (IsFPRegister()) { |
644 // We treat all FP register operands the same for simple aliasing. | 643 if (kSimpleFPAliasing) { |
645 canonical = MachineRepresentation::kFloat64; | 644 // We treat all FP register operands the same for simple aliasing. |
| 645 canonical = MachineRepresentation::kFloat64; |
| 646 } else { |
| 647 // We need to distinguish FP register operands of different reps when |
| 648 // aliasing is not simple (e.g. ARM). |
| 649 canonical = LocationOperand::cast(this)->representation(); |
| 650 } |
646 } | 651 } |
647 return InstructionOperand::KindField::update( | 652 return InstructionOperand::KindField::update( |
648 LocationOperand::RepresentationField::update(this->value_, canonical), | 653 LocationOperand::RepresentationField::update(this->value_, canonical), |
649 LocationOperand::EXPLICIT); | 654 LocationOperand::EXPLICIT); |
650 } | 655 } |
651 return this->value_; | 656 return this->value_; |
652 } | 657 } |
653 | 658 |
654 // Required for maps that don't care about machine type. | 659 // Required for maps that don't care about machine type. |
655 struct CompareOperandModuloType { | 660 struct CompareOperandModuloType { |
656 bool operator()(const InstructionOperand& a, | 661 bool operator()(const InstructionOperand& a, |
657 const InstructionOperand& b) const { | 662 const InstructionOperand& b) const { |
658 return a.CompareCanonicalized(b); | 663 return a.CompareCanonicalized(b); |
659 } | 664 } |
660 }; | 665 }; |
661 | 666 |
662 | 667 class V8_EXPORT_PRIVATE MoveOperands final |
663 class MoveOperands final : public ZoneObject { | 668 : public NON_EXPORTED_BASE(ZoneObject) { |
664 public: | 669 public: |
665 MoveOperands(const InstructionOperand& source, | 670 MoveOperands(const InstructionOperand& source, |
666 const InstructionOperand& destination) | 671 const InstructionOperand& destination) |
667 : source_(source), destination_(destination) { | 672 : source_(source), destination_(destination) { |
668 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); | 673 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); |
669 } | 674 } |
670 | 675 |
671 const InstructionOperand& source() const { return source_; } | 676 const InstructionOperand& source() const { return source_; } |
672 InstructionOperand& source() { return source_; } | 677 InstructionOperand& source() { return source_; } |
673 void set_source(const InstructionOperand& operand) { source_ = operand; } | 678 void set_source(const InstructionOperand& operand) { source_ = operand; } |
674 | 679 |
675 const InstructionOperand& destination() const { return destination_; } | 680 const InstructionOperand& destination() const { return destination_; } |
676 InstructionOperand& destination() { return destination_; } | 681 InstructionOperand& destination() { return destination_; } |
677 void set_destination(const InstructionOperand& operand) { | 682 void set_destination(const InstructionOperand& operand) { |
678 destination_ = operand; | 683 destination_ = operand; |
679 } | 684 } |
680 | 685 |
681 // The gap resolver marks moves as "in-progress" by clearing the | 686 // The gap resolver marks moves as "in-progress" by clearing the |
682 // destination (but not the source). | 687 // destination (but not the source). |
683 bool IsPending() const { | 688 bool IsPending() const { |
684 return destination_.IsInvalid() && !source_.IsInvalid(); | 689 return destination_.IsInvalid() && !source_.IsInvalid(); |
685 } | 690 } |
686 void SetPending() { destination_ = InstructionOperand(); } | 691 void SetPending() { destination_ = InstructionOperand(); } |
687 | 692 |
688 // True if this move is a move into the given destination operand. | |
689 bool Blocks(const InstructionOperand& destination) const { | |
690 return !IsEliminated() && source().InterferesWith(destination); | |
691 } | |
692 | |
693 // A move is redundant if it's been eliminated or if its source and | 693 // A move is redundant if it's been eliminated or if its source and |
694 // destination are the same. | 694 // destination are the same. |
695 bool IsRedundant() const { | 695 bool IsRedundant() const { |
696 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); | 696 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); |
697 return IsEliminated() || source_.EqualsCanonicalized(destination_); | 697 return IsEliminated() || source_.EqualsCanonicalized(destination_); |
698 } | 698 } |
699 | 699 |
700 // We clear both operands to indicate move that's been eliminated. | 700 // We clear both operands to indicate move that's been eliminated. |
701 void Eliminate() { source_ = destination_ = InstructionOperand(); } | 701 void Eliminate() { source_ = destination_ = InstructionOperand(); } |
702 bool IsEliminated() const { | 702 bool IsEliminated() const { |
(...skipping 14 matching lines...) Expand all Loading... |
717 | 717 |
718 | 718 |
719 struct PrintableMoveOperands { | 719 struct PrintableMoveOperands { |
720 const RegisterConfiguration* register_configuration_; | 720 const RegisterConfiguration* register_configuration_; |
721 const MoveOperands* move_operands_; | 721 const MoveOperands* move_operands_; |
722 }; | 722 }; |
723 | 723 |
724 | 724 |
725 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); | 725 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); |
726 | 726 |
727 | 727 class V8_EXPORT_PRIVATE ParallelMove final |
728 class ParallelMove final : public ZoneVector<MoveOperands*>, public ZoneObject { | 728 : public NON_EXPORTED_BASE(ZoneVector<MoveOperands *>), |
| 729 public NON_EXPORTED_BASE(ZoneObject) { |
729 public: | 730 public: |
730 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) { | 731 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) { |
731 reserve(4); | 732 reserve(4); |
732 } | 733 } |
733 | 734 |
734 MoveOperands* AddMove(const InstructionOperand& from, | 735 MoveOperands* AddMove(const InstructionOperand& from, |
735 const InstructionOperand& to) { | 736 const InstructionOperand& to) { |
736 Zone* zone = get_allocator().zone(); | 737 Zone* zone = get_allocator().zone(); |
737 return AddMove(from, to, zone); | 738 return AddMove(from, to, zone); |
738 } | 739 } |
739 | 740 |
740 MoveOperands* AddMove(const InstructionOperand& from, | 741 MoveOperands* AddMove(const InstructionOperand& from, |
741 const InstructionOperand& to, | 742 const InstructionOperand& to, |
742 Zone* operand_allocation_zone) { | 743 Zone* operand_allocation_zone) { |
743 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to); | 744 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to); |
744 push_back(move); | 745 push_back(move); |
745 return move; | 746 return move; |
746 } | 747 } |
747 | 748 |
748 bool IsRedundant() const; | 749 bool IsRedundant() const; |
749 | 750 |
750 // Prepare this ParallelMove to insert move as if it happened in a subsequent | 751 // Prepare this ParallelMove to insert move as if it happened in a subsequent |
751 // ParallelMove. move->source() may be changed. The MoveOperand returned | 752 // ParallelMove. move->source() may be changed. Any MoveOperands added to |
752 // must be Eliminated. | 753 // to_eliminate must be Eliminated. |
753 MoveOperands* PrepareInsertAfter(MoveOperands* move) const; | 754 void PrepareInsertAfter(MoveOperands* move, |
| 755 ZoneVector<MoveOperands*>* to_eliminate) const; |
754 | 756 |
755 private: | 757 private: |
756 DISALLOW_COPY_AND_ASSIGN(ParallelMove); | 758 DISALLOW_COPY_AND_ASSIGN(ParallelMove); |
757 }; | 759 }; |
758 | 760 |
759 | 761 |
760 struct PrintableParallelMove { | 762 struct PrintableParallelMove { |
761 const RegisterConfiguration* register_configuration_; | 763 const RegisterConfiguration* register_configuration_; |
762 const ParallelMove* parallel_move_; | 764 const ParallelMove* parallel_move_; |
763 }; | 765 }; |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1535 }; | 1537 }; |
1536 | 1538 |
1537 V8_EXPORT_PRIVATE std::ostream& operator<<( | 1539 V8_EXPORT_PRIVATE std::ostream& operator<<( |
1538 std::ostream& os, const PrintableInstructionSequence& code); | 1540 std::ostream& os, const PrintableInstructionSequence& code); |
1539 | 1541 |
1540 } // namespace compiler | 1542 } // namespace compiler |
1541 } // namespace internal | 1543 } // namespace internal |
1542 } // namespace v8 | 1544 } // namespace v8 |
1543 | 1545 |
1544 #endif // V8_COMPILER_INSTRUCTION_H_ | 1546 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |