Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// | 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 bool operator<(const RegWeight &A, const RegWeight &B); | 596 bool operator<(const RegWeight &A, const RegWeight &B); |
| 597 bool operator<=(const RegWeight &A, const RegWeight &B); | 597 bool operator<=(const RegWeight &A, const RegWeight &B); |
| 598 bool operator==(const RegWeight &A, const RegWeight &B); | 598 bool operator==(const RegWeight &A, const RegWeight &B); |
| 599 | 599 |
| 600 /// LiveRange is a set of instruction number intervals representing a variable's | 600 /// LiveRange is a set of instruction number intervals representing a variable's |
| 601 /// live range. Generally there is one interval per basic block where the | 601 /// live range. Generally there is one interval per basic block where the |
| 602 /// variable is live, but adjacent intervals get coalesced into a single | 602 /// variable is live, but adjacent intervals get coalesced into a single |
| 603 /// interval. | 603 /// interval. |
| 604 class LiveRange { | 604 class LiveRange { |
| 605 public: | 605 public: |
| 606 using RangeElementType = std::pair<InstNumberT, InstNumberT>; | |
| 607 /// RangeType is arena-allocated from the Cfg's allocator. | |
| 608 using RangeType = CfgVector<RangeElementType>; | |
| 606 LiveRange() = default; | 609 LiveRange() = default; |
| 607 /// Special constructor for building a kill set. The advantage is that we can | 610 /// Special constructor for building a kill set. The advantage is that we can |
| 608 /// reserve the right amount of space in advance. | 611 /// reserve the right amount of space in advance. |
| 609 explicit LiveRange(const CfgVector<InstNumberT> &Kills) { | 612 explicit LiveRange(const CfgVector<InstNumberT> &Kills) { |
| 610 Range.reserve(Kills.size()); | 613 Range.reserve(Kills.size()); |
| 611 for (InstNumberT I : Kills) | 614 for (InstNumberT I : Kills) |
| 612 addSegment(I, I); | 615 addSegment(I, I); |
| 613 } | 616 } |
| 614 LiveRange(const LiveRange &) = default; | 617 LiveRange(const LiveRange &) = default; |
| 615 LiveRange &operator=(const LiveRange &) = default; | 618 LiveRange &operator=(const LiveRange &) = default; |
| 616 | 619 |
| 617 void reset() { | 620 void reset() { |
| 618 Range.clear(); | 621 Range.clear(); |
| 619 untrim(); | 622 untrim(); |
| 620 } | 623 } |
| 621 void addSegment(InstNumberT Start, InstNumberT End); | 624 void addSegment(InstNumberT Start, InstNumberT End, CfgNode *Node = nullptr); |
| 625 void addSegment(RangeElementType Segment) { | |
|
Jim Stichnoth
2016/07/29 17:04:07
How about:
void addSegment(RangeElementType Segme
manasijm
2016/08/01 22:20:04
Done.
| |
| 626 addSegment(Segment.first, Segment.second); | |
| 627 } | |
| 622 | 628 |
| 623 bool endsBefore(const LiveRange &Other) const; | 629 bool endsBefore(const LiveRange &Other) const; |
| 624 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; | 630 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; |
| 625 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; | 631 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; |
| 626 bool containsValue(InstNumberT Value, bool IsDest) const; | 632 bool containsValue(InstNumberT Value, bool IsDest) const; |
| 627 bool isEmpty() const { return Range.empty(); } | 633 bool isEmpty() const { return Range.empty(); } |
| 628 InstNumberT getStart() const { | 634 InstNumberT getStart() const { |
| 629 return Range.empty() ? -1 : Range.begin()->first; | 635 return Range.empty() ? -1 : Range.begin()->first; |
| 630 } | 636 } |
| 631 InstNumberT getEnd() const { | 637 InstNumberT getEnd() const { |
| 632 return Range.empty() ? -1 : Range.rbegin()->second; | 638 return Range.empty() ? -1 : Range.rbegin()->second; |
| 633 } | 639 } |
| 634 | 640 |
| 635 void untrim() { TrimmedBegin = Range.begin(); } | 641 void untrim() { TrimmedBegin = Range.begin(); } |
| 636 void trim(InstNumberT Lower); | 642 void trim(InstNumberT Lower); |
| 637 | 643 |
| 638 void dump(Ostream &Str) const; | 644 void dump(Ostream &Str) const; |
| 639 | 645 |
| 646 SizeT getNumSegments() { return Range.size(); } | |
|
Jim Stichnoth
2016/07/29 17:04:07
SizeT getNumSegments() const ...
manasijm
2016/08/01 22:20:03
Done.
| |
| 647 | |
| 648 const RangeType &getSegments() { return Range; } | |
|
Jim Stichnoth
2016/07/29 17:04:07
can this be const?
manasijm
2016/08/01 22:20:03
Done.
| |
| 649 CfgNode *getNodeForSegment(InstNumberT Begin) { return NodeMap[Begin]; } | |
|
Jim Stichnoth
2016/07/29 17:04:07
const?
manasijm
2016/08/01 22:20:04
Probably not.
| |
| 650 | |
| 640 private: | 651 private: |
| 641 using RangeElementType = std::pair<InstNumberT, InstNumberT>; | |
| 642 /// RangeType is arena-allocated from the Cfg's allocator. | |
| 643 using RangeType = CfgVector<RangeElementType>; | |
| 644 RangeType Range; | 652 RangeType Range; |
| 653 CfgUnorderedMap<InstNumberT, CfgNode *> NodeMap; | |
| 645 /// TrimmedBegin is an optimization for the overlaps() computation. Since the | 654 /// TrimmedBegin is an optimization for the overlaps() computation. Since the |
| 646 /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances | 655 /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances |
| 647 /// monotonically according to live range start, we can optimize overlaps() by | 656 /// monotonically according to live range start, we can optimize overlaps() by |
| 648 /// ignoring all segments that end before the start of Cur's range. The | 657 /// ignoring all segments that end before the start of Cur's range. The |
| 649 /// linear-scan code enables this by calling trim() on the ranges of interest | 658 /// linear-scan code enables this by calling trim() on the ranges of interest |
| 650 /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin | 659 /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin |
| 651 /// at the beginning by calling untrim(). | 660 /// at the beginning by calling untrim(). |
| 652 RangeType::const_iterator TrimmedBegin; | 661 RangeType::const_iterator TrimmedBegin; |
| 653 }; | 662 }; |
| 654 | 663 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 668 RR_MustNotHaveRegister, | 677 RR_MustNotHaveRegister, |
| 669 }; | 678 }; |
| 670 | 679 |
| 671 public: | 680 public: |
| 672 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { | 681 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { |
| 673 return new (Func->allocate<Variable>()) | 682 return new (Func->allocate<Variable>()) |
| 674 Variable(Func, kVariable, Ty, Index); | 683 Variable(Func, kVariable, Ty, Index); |
| 675 } | 684 } |
| 676 | 685 |
| 677 SizeT getIndex() const { return Number; } | 686 SizeT getIndex() const { return Number; } |
| 687 void setIndex(SizeT NewIndex) { Number = NewIndex; } | |
| 678 std::string getName() const { | 688 std::string getName() const { |
| 679 if (Name.hasStdString()) | 689 if (Name.hasStdString()) |
| 680 return Name.toString(); | 690 return Name.toString(); |
| 681 return "__" + std::to_string(getIndex()); | 691 return "__" + std::to_string(getIndex()); |
| 682 } | 692 } |
| 683 virtual void setName(const Cfg *Func, const std::string &NewName) { | 693 virtual void setName(const Cfg *Func, const std::string &NewName) { |
| 684 if (NewName.empty()) | 694 if (NewName.empty()) |
| 685 return; | 695 return; |
| 686 Name = VariableString::createWithString(Func, NewName); | 696 Name = VariableString::createWithString(Func, NewName); |
| 687 } | 697 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 737 } | 747 } |
| 738 bool isRematerializable() const { return IsRematerializable; } | 748 bool isRematerializable() const { return IsRematerializable; } |
| 739 | 749 |
| 740 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); } | 750 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); } |
| 741 RegClass getRegClass() const { return RegisterClass; } | 751 RegClass getRegClass() const { return RegisterClass; } |
| 742 | 752 |
| 743 LiveRange &getLiveRange() { return Live; } | 753 LiveRange &getLiveRange() { return Live; } |
| 744 const LiveRange &getLiveRange() const { return Live; } | 754 const LiveRange &getLiveRange() const { return Live; } |
| 745 void setLiveRange(const LiveRange &Range) { Live = Range; } | 755 void setLiveRange(const LiveRange &Range) { Live = Range; } |
| 746 void resetLiveRange() { Live.reset(); } | 756 void resetLiveRange() { Live.reset(); } |
| 747 void addLiveRange(InstNumberT Start, InstNumberT End) { | 757 void addLiveRange(InstNumberT Start, InstNumberT End, |
| 758 CfgNode *Node = nullptr) { | |
| 748 assert(!getIgnoreLiveness()); | 759 assert(!getIgnoreLiveness()); |
| 749 Live.addSegment(Start, End); | 760 Live.addSegment(Start, End, Node); |
| 750 } | 761 } |
| 751 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } | 762 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } |
| 752 void untrimLiveRange() { Live.untrim(); } | 763 void untrimLiveRange() { Live.untrim(); } |
| 753 bool rangeEndsBefore(const Variable *Other) const { | 764 bool rangeEndsBefore(const Variable *Other) const { |
| 754 return Live.endsBefore(Other->Live); | 765 return Live.endsBefore(Other->Live); |
| 755 } | 766 } |
| 756 bool rangeOverlaps(const Variable *Other) const { | 767 bool rangeOverlaps(const Variable *Other) const { |
| 757 constexpr bool UseTrimmed = true; | 768 constexpr bool UseTrimmed = true; |
| 758 return Live.overlaps(Other->Live, UseTrimmed); | 769 return Live.overlaps(Other->Live, UseTrimmed); |
| 759 } | 770 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 Variable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index) | 812 Variable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index) |
| 802 : Operand(K, Ty), Number(Index), | 813 : Operand(K, Ty), Number(Index), |
| 803 Name(VariableString::createWithoutString(Func)), | 814 Name(VariableString::createWithoutString(Func)), |
| 804 RegisterClass(static_cast<RegClass>(Ty)) { | 815 RegisterClass(static_cast<RegClass>(Ty)) { |
| 805 Vars = VarsReal; | 816 Vars = VarsReal; |
| 806 Vars[0] = this; | 817 Vars[0] = this; |
| 807 NumVars = 1; | 818 NumVars = 1; |
| 808 } | 819 } |
| 809 /// Number is unique across all variables, and is used as a (bit)vector index | 820 /// Number is unique across all variables, and is used as a (bit)vector index |
| 810 /// for liveness analysis. | 821 /// for liveness analysis. |
| 811 const SizeT Number; | 822 SizeT Number; |
| 812 VariableString Name; | 823 VariableString Name; |
| 813 bool IsArgument = false; | 824 bool IsArgument = false; |
| 814 bool IsImplicitArgument = false; | 825 bool IsImplicitArgument = false; |
| 815 /// IgnoreLiveness means that the variable should be ignored when constructing | 826 /// IgnoreLiveness means that the variable should be ignored when constructing |
| 816 /// and validating live ranges. This is usually reserved for the stack | 827 /// and validating live ranges. This is usually reserved for the stack |
| 817 /// pointer and other physical registers specifically referenced by name. | 828 /// pointer and other physical registers specifically referenced by name. |
| 818 bool IgnoreLiveness = false; | 829 bool IgnoreLiveness = false; |
| 819 // If IsRematerializable, RegNum keeps track of which register (stack or frame | 830 // If IsRematerializable, RegNum keeps track of which register (stack or frame |
| 820 // pointer), and StackOffset is the known offset from that register. | 831 // pointer), and StackOffset is the known offset from that register. |
| 821 bool IsRematerializable = false; | 832 bool IsRematerializable = false; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1044 return Operand->getKind() == kVariableBoolean; | 1055 return Operand->getKind() == kVariableBoolean; |
| 1045 } | 1056 } |
| 1046 | 1057 |
| 1047 private: | 1058 private: |
| 1048 Variable *BoolSource = nullptr; | 1059 Variable *BoolSource = nullptr; |
| 1049 }; | 1060 }; |
| 1050 | 1061 |
| 1051 } // end of namespace Ice | 1062 } // end of namespace Ice |
| 1052 | 1063 |
| 1053 #endif // SUBZERO_SRC_ICEOPERAND_H | 1064 #endif // SUBZERO_SRC_ICEOPERAND_H |
| OLD | NEW |