| 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 |