| 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 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 | 396 |
| 397 static bool classof(const Operand *Operand) { | 397 static bool classof(const Operand *Operand) { |
| 398 return Operand->getKind() == kConstUndef; | 398 return Operand->getKind() == kConstUndef; |
| 399 } | 399 } |
| 400 | 400 |
| 401 private: | 401 private: |
| 402 ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {} | 402 ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {} |
| 403 }; | 403 }; |
| 404 | 404 |
| 405 /// RegNumT is for holding target-specific register numbers, plus the sentinel | 405 /// RegNumT is for holding target-specific register numbers, plus the sentinel |
| 406 /// value NoRegister. Its public ctor allows direct use of enum values, such as | 406 /// value if no register is assigned. Its public ctor allows direct use of enum |
| 407 /// RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1). This is to try to | 407 /// values, such as RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1). |
| 408 /// prevent inappropriate assumptions about enum ordering. If needed, the | 408 /// This is to try to prevent inappropriate assumptions about enum ordering. If |
| 409 /// fromInt() method can be used, such as when a RegNumT is based on a bitvector | 409 /// needed, the fromInt() method can be used, such as when a RegNumT is based |
| 410 /// index. | 410 /// on a bitvector index. |
| 411 class RegNumT { | 411 class RegNumT { |
| 412 public: | 412 public: |
| 413 using BaseType = uint32_t; | 413 using BaseType = uint32_t; |
| 414 RegNumT() = default; | 414 RegNumT() = default; |
| 415 RegNumT(const RegNumT &) = default; | 415 RegNumT(const RegNumT &) = default; |
| 416 template <typename AnyEnum> | 416 template <typename AnyEnum> |
| 417 RegNumT(AnyEnum Value, | 417 RegNumT(AnyEnum Value, |
| 418 typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0) | 418 typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0) |
| 419 : Value(Value) { | 419 : Value(Value) { |
| 420 validate(Value); | 420 validate(Value); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 434 /// upper bound of allowable values. | 434 /// upper bound of allowable values. |
| 435 static void setLimit(BaseType Value) { | 435 static void setLimit(BaseType Value) { |
| 436 // Make sure it's only called once. | 436 // Make sure it's only called once. |
| 437 assert(Limit == 0); | 437 assert(Limit == 0); |
| 438 assert(Value != 0); | 438 assert(Value != 0); |
| 439 Limit = Value; | 439 Limit = Value; |
| 440 } | 440 } |
| 441 // Define NoRegisterValue as an enum value so that it can be used as an | 441 // Define NoRegisterValue as an enum value so that it can be used as an |
| 442 // argument for the public ctor if desired. | 442 // argument for the public ctor if desired. |
| 443 enum { NoRegisterValue = std::numeric_limits<BaseType>::max() }; | 443 enum { NoRegisterValue = std::numeric_limits<BaseType>::max() }; |
| 444 const static RegNumT NoRegister /* = NoRegisterValue */; | 444 |
| 445 bool hasValue() const { return Value != NoRegisterValue; } |
| 446 bool hasNoValue() const { return !hasValue(); } |
| 445 | 447 |
| 446 private: | 448 private: |
| 447 BaseType Value = NoRegisterValue; | 449 BaseType Value = NoRegisterValue; |
| 448 static BaseType Limit; | 450 static BaseType Limit; |
| 449 /// Private ctor called only by fromInt() and fixme(). | 451 /// Private ctor called only by fromInt() and fixme(). |
| 450 RegNumT(BaseType Value) : Value(Value) { validate(Value); } | 452 RegNumT(BaseType Value) : Value(Value) { validate(Value); } |
| 451 /// The ctor calls this to validate against the target-supplied limit. | 453 /// The ctor calls this to validate against the target-supplied limit. |
| 452 static void validate(BaseType Value) { | 454 static void validate(BaseType Value) { |
| 453 (void)Value; | 455 (void)Value; |
| 454 assert(Value == NoRegisterValue || Value < Limit); | 456 assert(Value == NoRegisterValue || Value < Limit); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 bool getIgnoreLiveness() const { return IgnoreLiveness; } | 641 bool getIgnoreLiveness() const { return IgnoreLiveness; } |
| 640 | 642 |
| 641 int32_t getStackOffset() const { return StackOffset; } | 643 int32_t getStackOffset() const { return StackOffset; } |
| 642 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 644 void setStackOffset(int32_t Offset) { StackOffset = Offset; } |
| 643 /// Returns the variable's stack offset in symbolic form, to improve | 645 /// Returns the variable's stack offset in symbolic form, to improve |
| 644 /// readability in DecorateAsm mode. | 646 /// readability in DecorateAsm mode. |
| 645 IceString getSymbolicStackOffset(const Cfg *Func) const { | 647 IceString getSymbolicStackOffset(const Cfg *Func) const { |
| 646 return "lv$" + getName(Func); | 648 return "lv$" + getName(Func); |
| 647 } | 649 } |
| 648 | 650 |
| 649 bool hasReg() const { return getRegNum() != RegNumT::NoRegister; } | 651 bool hasReg() const { return getRegNum().hasValue(); } |
| 650 RegNumT getRegNum() const { return RegNum; } | 652 RegNumT getRegNum() const { return RegNum; } |
| 651 void setRegNum(RegNumT NewRegNum) { | 653 void setRegNum(RegNumT NewRegNum) { |
| 652 // Regnum shouldn't be set more than once. | 654 // Regnum shouldn't be set more than once. |
| 653 assert(!hasReg() || RegNum == NewRegNum); | 655 assert(!hasReg() || RegNum == NewRegNum); |
| 654 RegNum = NewRegNum; | 656 RegNum = NewRegNum; |
| 655 } | 657 } |
| 656 bool hasRegTmp() const { return getRegNumTmp() != RegNumT::NoRegister; } | 658 bool hasRegTmp() const { return getRegNumTmp().hasValue(); } |
| 657 RegNumT getRegNumTmp() const { return RegNumTmp; } | 659 RegNumT getRegNumTmp() const { return RegNumTmp; } |
| 658 void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; } | 660 void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; } |
| 659 | 661 |
| 660 RegWeight getWeight(const Cfg *Func) const; | 662 RegWeight getWeight(const Cfg *Func) const; |
| 661 | 663 |
| 662 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; } | 664 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; } |
| 663 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; } | 665 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; } |
| 664 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; } | 666 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; } |
| 665 bool mustNotHaveReg() const { | 667 bool mustNotHaveReg() const { |
| 666 return RegRequirement == RR_MustNotHaveRegister; | 668 return RegRequirement == RR_MustNotHaveRegister; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 695 } | 697 } |
| 696 bool rangeOverlapsStart(const Variable *Other) const { | 698 bool rangeOverlapsStart(const Variable *Other) const { |
| 697 constexpr bool UseTrimmed = true; | 699 constexpr bool UseTrimmed = true; |
| 698 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 700 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); |
| 699 } | 701 } |
| 700 | 702 |
| 701 /// Creates a temporary copy of the variable with a different type. Used | 703 /// Creates a temporary copy of the variable with a different type. Used |
| 702 /// primarily for syntactic correctness of textual assembly emission. Note | 704 /// primarily for syntactic correctness of textual assembly emission. Note |
| 703 /// that only basic information is copied, in particular not IsArgument, | 705 /// that only basic information is copied, in particular not IsArgument, |
| 704 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, | 706 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, |
| 705 /// VarsReal. If NewRegNum!=NoRegister, then that register assignment is made | 707 /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made |
| 706 /// instead of copying the existing assignment. | 708 /// instead of copying the existing assignment. |
| 707 const Variable *asType(Type Ty, RegNumT NewRegNum) const; | 709 const Variable *asType(Type Ty, RegNumT NewRegNum) const; |
| 708 | 710 |
| 709 void emit(const Cfg *Func) const override; | 711 void emit(const Cfg *Func) const override; |
| 710 using Operand::dump; | 712 using Operand::dump; |
| 711 void dump(const Cfg *Func, Ostream &Str) const override; | 713 void dump(const Cfg *Func, Ostream &Str) const override; |
| 712 | 714 |
| 713 /// Return reg num of base register, if different from stack/frame register. | 715 /// Return reg num of base register, if different from stack/frame register. |
| 714 virtual RegNumT getBaseRegNum() const { return RegNumT::NoRegister; } | 716 virtual RegNumT getBaseRegNum() const { return RegNumT(); } |
| 715 | 717 |
| 716 static bool classof(const Operand *Operand) { | 718 static bool classof(const Operand *Operand) { |
| 717 OperandKind Kind = Operand->getKind(); | 719 OperandKind Kind = Operand->getKind(); |
| 718 return Kind >= kVariable && Kind <= kVariable_Max; | 720 return Kind >= kVariable && Kind <= kVariable_Max; |
| 719 } | 721 } |
| 720 | 722 |
| 721 protected: | 723 protected: |
| 722 Variable(OperandKind K, Type Ty, SizeT Index) | 724 Variable(OperandKind K, Type Ty, SizeT Index) |
| 723 : Operand(K, Ty), Number(Index), | 725 : Operand(K, Ty), Number(Index), |
| 724 RegisterClass(static_cast<RegClass>(Ty)) { | 726 RegisterClass(static_cast<RegClass>(Ty)) { |
| 725 Vars = VarsReal; | 727 Vars = VarsReal; |
| 726 Vars[0] = this; | 728 Vars[0] = this; |
| 727 NumVars = 1; | 729 NumVars = 1; |
| 728 } | 730 } |
| 729 /// Number is unique across all variables, and is used as a (bit)vector index | 731 /// Number is unique across all variables, and is used as a (bit)vector index |
| 730 /// for liveness analysis. | 732 /// for liveness analysis. |
| 731 const SizeT Number; | 733 const SizeT Number; |
| 732 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; | 734 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; |
| 733 bool IsArgument = false; | 735 bool IsArgument = false; |
| 734 bool IsImplicitArgument = false; | 736 bool IsImplicitArgument = false; |
| 735 /// IgnoreLiveness means that the variable should be ignored when constructing | 737 /// IgnoreLiveness means that the variable should be ignored when constructing |
| 736 /// and validating live ranges. This is usually reserved for the stack | 738 /// and validating live ranges. This is usually reserved for the stack |
| 737 /// pointer and other physical registers specifically referenced by name. | 739 /// pointer and other physical registers specifically referenced by name. |
| 738 bool IgnoreLiveness = false; | 740 bool IgnoreLiveness = false; |
| 739 // If IsRematerializable, RegNum keeps track of which register (stack or frame | 741 // If IsRematerializable, RegNum keeps track of which register (stack or frame |
| 740 // pointer), and StackOffset is the known offset from that register. | 742 // pointer), and StackOffset is the known offset from that register. |
| 741 bool IsRematerializable = false; | 743 bool IsRematerializable = false; |
| 742 RegRequirement RegRequirement = RR_MayHaveRegister; | 744 RegRequirement RegRequirement = RR_MayHaveRegister; |
| 743 RegClass RegisterClass; | 745 RegClass RegisterClass; |
| 744 /// RegNum is the allocated register, or NoRegister if it isn't | 746 /// RegNum is the allocated register, (as long as RegNum.hasValue() is true). |
| 745 /// register-allocated. | 747 RegNumT RegNum; |
| 746 RegNumT RegNum = RegNumT::NoRegister; | |
| 747 /// RegNumTmp is the tentative assignment during register allocation. | 748 /// RegNumTmp is the tentative assignment during register allocation. |
| 748 RegNumT RegNumTmp = RegNumT::NoRegister; | 749 RegNumT RegNumTmp; |
| 749 /// StackOffset is the canonical location on stack (only if | 750 /// StackOffset is the canonical location on stack (only if |
| 750 /// RegNum==NoRegister || IsArgument). | 751 /// RegNum.hasNoValue() || IsArgument). |
| 751 int32_t StackOffset = 0; | 752 int32_t StackOffset = 0; |
| 752 LiveRange Live; | 753 LiveRange Live; |
| 753 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. | 754 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. |
| 754 Variable *VarsReal[1]; | 755 Variable *VarsReal[1]; |
| 755 }; | 756 }; |
| 756 | 757 |
| 757 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In | 758 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In |
| 758 // this situation the variable must be split into a low and a high word. | 759 // this situation the variable must be split into a low and a high word. |
| 759 class Variable64On32 : public Variable { | 760 class Variable64On32 : public Variable { |
| 760 Variable64On32() = delete; | 761 Variable64On32() = delete; |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 private: | 924 private: |
| 924 const Cfg *Func; | 925 const Cfg *Func; |
| 925 MetadataKind Kind; | 926 MetadataKind Kind; |
| 926 CfgVector<VariableTracking> Metadata; | 927 CfgVector<VariableTracking> Metadata; |
| 927 const static InstDefList NoDefinitions; | 928 const static InstDefList NoDefinitions; |
| 928 }; | 929 }; |
| 929 | 930 |
| 930 } // end of namespace Ice | 931 } // end of namespace Ice |
| 931 | 932 |
| 932 #endif // SUBZERO_SRC_ICEOPERAND_H | 933 #endif // SUBZERO_SRC_ICEOPERAND_H |
| OLD | NEW |