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 : public ZoneObject { |
jochen (gone - plz use gerrit)
2016/10/25 11:56:07
if you export a class, you have to annotated unexp
bbudge
2016/10/25 14:01:09
Done. Here and below.
| |
663 class MoveOperands final : public ZoneObject { | |
664 public: | 668 public: |
665 MoveOperands(const InstructionOperand& source, | 669 MoveOperands(const InstructionOperand& source, |
666 const InstructionOperand& destination) | 670 const InstructionOperand& destination) |
667 : source_(source), destination_(destination) { | 671 : source_(source), destination_(destination) { |
668 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); | 672 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); |
669 } | 673 } |
670 | 674 |
671 const InstructionOperand& source() const { return source_; } | 675 const InstructionOperand& source() const { return source_; } |
672 InstructionOperand& source() { return source_; } | 676 InstructionOperand& source() { return source_; } |
673 void set_source(const InstructionOperand& operand) { source_ = operand; } | 677 void set_source(const InstructionOperand& operand) { source_ = operand; } |
674 | 678 |
675 const InstructionOperand& destination() const { return destination_; } | 679 const InstructionOperand& destination() const { return destination_; } |
676 InstructionOperand& destination() { return destination_; } | 680 InstructionOperand& destination() { return destination_; } |
677 void set_destination(const InstructionOperand& operand) { | 681 void set_destination(const InstructionOperand& operand) { |
678 destination_ = operand; | 682 destination_ = operand; |
679 } | 683 } |
680 | 684 |
681 // The gap resolver marks moves as "in-progress" by clearing the | 685 // The gap resolver marks moves as "in-progress" by clearing the |
682 // destination (but not the source). | 686 // destination (but not the source). |
683 bool IsPending() const { | 687 bool IsPending() const { |
684 return destination_.IsInvalid() && !source_.IsInvalid(); | 688 return destination_.IsInvalid() && !source_.IsInvalid(); |
685 } | 689 } |
686 void SetPending() { destination_ = InstructionOperand(); } | 690 void SetPending() { destination_ = InstructionOperand(); } |
687 | 691 |
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 | 692 // A move is redundant if it's been eliminated or if its source and |
694 // destination are the same. | 693 // destination are the same. |
695 bool IsRedundant() const { | 694 bool IsRedundant() const { |
696 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); | 695 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); |
697 return IsEliminated() || source_.EqualsCanonicalized(destination_); | 696 return IsEliminated() || source_.EqualsCanonicalized(destination_); |
698 } | 697 } |
699 | 698 |
700 // We clear both operands to indicate move that's been eliminated. | 699 // We clear both operands to indicate move that's been eliminated. |
701 void Eliminate() { source_ = destination_ = InstructionOperand(); } | 700 void Eliminate() { source_ = destination_ = InstructionOperand(); } |
702 bool IsEliminated() const { | 701 bool IsEliminated() const { |
(...skipping 14 matching lines...) Expand all Loading... | |
717 | 716 |
718 | 717 |
719 struct PrintableMoveOperands { | 718 struct PrintableMoveOperands { |
720 const RegisterConfiguration* register_configuration_; | 719 const RegisterConfiguration* register_configuration_; |
721 const MoveOperands* move_operands_; | 720 const MoveOperands* move_operands_; |
722 }; | 721 }; |
723 | 722 |
724 | 723 |
725 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); | 724 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); |
726 | 725 |
727 | 726 class V8_EXPORT_PRIVATE ParallelMove final : public ZoneVector<MoveOperands *>, |
jochen (gone - plz use gerrit)
2016/10/25 11:56:07
ZoneVector<T> is implemented as std::vector<T, zon
bbudge
2016/10/25 14:01:09
I stumbled on that fix in patchset #22 (adding a d
| |
728 class ParallelMove final : public ZoneVector<MoveOperands*>, public ZoneObject { | 727 public ZoneObject { |
729 public: | 728 public: |
730 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) { | 729 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) { |
731 reserve(4); | 730 reserve(4); |
732 } | 731 } |
733 | 732 |
734 MoveOperands* AddMove(const InstructionOperand& from, | 733 MoveOperands* AddMove(const InstructionOperand& from, |
735 const InstructionOperand& to) { | 734 const InstructionOperand& to) { |
736 Zone* zone = get_allocator().zone(); | 735 Zone* zone = get_allocator().zone(); |
737 return AddMove(from, to, zone); | 736 return AddMove(from, to, zone); |
738 } | 737 } |
739 | 738 |
740 MoveOperands* AddMove(const InstructionOperand& from, | 739 MoveOperands* AddMove(const InstructionOperand& from, |
741 const InstructionOperand& to, | 740 const InstructionOperand& to, |
742 Zone* operand_allocation_zone) { | 741 Zone* operand_allocation_zone) { |
743 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to); | 742 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to); |
744 push_back(move); | 743 push_back(move); |
745 return move; | 744 return move; |
746 } | 745 } |
747 | 746 |
748 bool IsRedundant() const; | 747 bool IsRedundant() const; |
749 | 748 |
750 // Prepare this ParallelMove to insert move as if it happened in a subsequent | 749 // Prepare this ParallelMove to insert move as if it happened in a subsequent |
751 // ParallelMove. move->source() may be changed. The MoveOperand returned | 750 // ParallelMove. move->source() may be changed. Any MoveOperands added to |
752 // must be Eliminated. | 751 // to_eliminate must be Eliminated. |
753 MoveOperands* PrepareInsertAfter(MoveOperands* move) const; | 752 void PrepareInsertAfter(MoveOperands* move, |
753 ZoneVector<MoveOperands*>* to_eliminate) const; | |
754 | 754 |
755 private: | 755 private: |
756 DISALLOW_COPY_AND_ASSIGN(ParallelMove); | 756 DISALLOW_COPY_AND_ASSIGN(ParallelMove); |
757 }; | 757 }; |
758 | 758 |
759 | 759 |
760 struct PrintableParallelMove { | 760 struct PrintableParallelMove { |
761 const RegisterConfiguration* register_configuration_; | 761 const RegisterConfiguration* register_configuration_; |
762 const ParallelMove* parallel_move_; | 762 const ParallelMove* parallel_move_; |
763 }; | 763 }; |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1535 }; | 1535 }; |
1536 | 1536 |
1537 V8_EXPORT_PRIVATE std::ostream& operator<<( | 1537 V8_EXPORT_PRIVATE std::ostream& operator<<( |
1538 std::ostream& os, const PrintableInstructionSequence& code); | 1538 std::ostream& os, const PrintableInstructionSequence& code); |
1539 | 1539 |
1540 } // namespace compiler | 1540 } // namespace compiler |
1541 } // namespace internal | 1541 } // namespace internal |
1542 } // namespace v8 | 1542 } // namespace v8 |
1543 | 1543 |
1544 #endif // V8_COMPILER_INSTRUCTION_H_ | 1544 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |