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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 } | 395 } | 
| 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 | |
| 406 /// value NoRegister. Its public ctor allows direct use of enum values, such as | |
| 407 /// RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1). This is to try to | |
| 408 /// prevent inappropriate assumptions about enum ordering. If needed, the | |
| 409 /// fromInt() method can be used, such as when a RegNumT is based on a bitvector | |
| 410 /// index. | |
| 411 class RegNumT { | |
| 412 public: | |
| 413 using BaseType = uint32_t; | |
| 414 RegNumT() = default; | |
| 415 RegNumT(const RegNumT &) = default; | |
| 416 template <typename AnyEnum> | |
| 417 RegNumT(AnyEnum Value, | |
| 418 typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0) | |
| 419 : Value(Value) { | |
| 420 validate(Value); | |
| 421 } | |
| 422 RegNumT &operator=(const RegNumT &) = default; | |
| 423 operator unsigned() const { return Value; } | |
| 424 /// Asserts that the register is valid, i.e. not NoRegister. Note that the | |
| 425 /// ctor already does the target-specific limit check. | |
| 426 void assertIsValid() const { assert(Value != NoRegister); } | |
| 427 static RegNumT fromInt(BaseType Value) { return RegNumT(Value); } | |
| 428 /// Marks cases that inappropriately add/subtract RegNumT values, and | |
| 429 /// therefore need to be fixed because they make assumptions about register | |
| 430 /// enum value ordering. TODO(stichnot): Remove fixme() as soon as all | |
| 431 /// current uses are fixed/removed. | |
| 432 static RegNumT fixme(BaseType Value) { return RegNumT(Value); } | |
| 433 /// The target's staticInit() method should call setLimit() to register the | |
| 434 /// upper bound of allowable values. | |
| 435 static void setLimit(BaseType Value) { | |
| 436 // Make sure it's only called once. | |
| 437 assert(Limit == 0); | |
| 438 assert(Value != 0); | |
| 439 Limit = Value; | |
| 440 } | |
| 441 // Define NoRegister as an enum value so that it can be used as an argument | |
| 
 
John
2016/02/10 16:01:51
nice. :)
 
Jim Stichnoth
2016/02/10 17:47:20
True, though that inhibits certain uses of "auto",
 
Jim Stichnoth
2016/02/10 18:47:30
I am now le refreshed, and realize the horror of t
 
 | |
| 442 // for the public ctor. | |
| 443 enum { NoRegister = std::numeric_limits<BaseType>::max() }; | |
| 444 | |
| 445 private: | |
| 446 BaseType Value = NoRegister; | |
| 447 static BaseType Limit; | |
| 448 /// Private ctor called only by fromInt() and fixme(). | |
| 449 RegNumT(BaseType Value) : Value(Value) { validate(Value); } | |
| 450 /// The ctor calls this to validate against the target-supplied limit. | |
| 451 static void validate(BaseType Value) { | |
| 452 (void)Value; | |
| 453 assert(Value == NoRegister || Value < Limit); | |
| 454 } | |
| 455 /// Disallow operators that inappropriately make assumptions about register | |
| 456 /// enum value ordering. | |
| 457 bool operator<(const RegNumT &) = delete; | |
| 458 bool operator<=(const RegNumT &) = delete; | |
| 459 bool operator>(const RegNumT &) = delete; | |
| 460 bool operator>=(const RegNumT &) = delete; | |
| 461 }; | |
| 462 | |
| 463 /// RegNumBitVector wraps llvm::SmallBitVector so that instead of this pattern: | |
| 464 /// | |
| 465 /// for (int i = V.find_first(); i != -1; i = V.find_next(i)) { | |
| 466 /// RegNumT RegNum = RegNumT::fromInt(i); | |
| 467 /// ... | |
| 468 /// } | |
| 469 /// | |
| 470 /// this cleaner pattern can be used: | |
| 471 /// | |
| 472 /// for (RegNumT RegNum : RegNumBitVector(V)) { | |
| 473 /// ... | |
| 474 /// } | |
| 475 class RegNumBitVector { | |
| 
 
John
2016/02/10 16:01:51
This is an iterator, so maybe just rename it to Re
 
Jim Stichnoth
2016/02/10 17:47:20
I was trying to control the identifier length a bi
 
 | |
| 476 using T = llvm::SmallBitVector; | |
| 477 static constexpr int Sentinel = -1; | |
| 478 RegNumBitVector() = delete; | |
| 479 RegNumBitVector(const RegNumBitVector &) = delete; | |
| 480 RegNumBitVector &operator=(const RegNumBitVector &) = delete; | |
| 481 | |
| 482 public: | |
| 483 class Iterator { | |
| 484 Iterator() = delete; | |
| 485 Iterator &operator=(const Iterator &) = delete; | |
| 486 | |
| 487 public: | |
| 488 explicit Iterator(const T &V) : V(V), Current(V.find_first()) {} | |
| 489 Iterator(const T &V, int Value) : V(V), Current(Value) {} | |
| 490 Iterator(const Iterator &) = default; | |
| 491 RegNumT operator*() { | |
| 492 assert(Current != Sentinel); | |
| 493 return RegNumT::fromInt(Current); | |
| 494 } | |
| 495 Iterator &operator++() { | |
| 496 assert(Current != Sentinel); | |
| 497 Current = V.find_next(Current); | |
| 498 return *this; | |
| 499 } | |
| 500 bool operator!=(Iterator &Other) { return Current != Other.Current; } | |
| 501 | |
| 502 private: | |
| 503 const T &V; | |
| 504 int Current; | |
| 505 }; | |
| 506 | |
| 507 explicit RegNumBitVector(const T &V) : V(V) {} | |
| 508 Iterator begin() { return Iterator(V); } | |
| 509 Iterator end() { return Iterator(V, Sentinel); } | |
| 510 | |
| 511 private: | |
| 512 const T &V; | |
| 513 }; | |
| 514 | |
| 405 /// RegWeight is a wrapper for a uint32_t weight value, with a special value | 515 /// RegWeight is a wrapper for a uint32_t weight value, with a special value | 
| 406 /// that represents infinite weight, and an addWeight() method that ensures that | 516 /// that represents infinite weight, and an addWeight() method that ensures that | 
| 407 /// W+infinity=infinity. | 517 /// W+infinity=infinity. | 
| 408 class RegWeight { | 518 class RegWeight { | 
| 409 public: | 519 public: | 
| 410 RegWeight() = default; | 520 RegWeight() = default; | 
| 411 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} | 521 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} | 
| 412 RegWeight(const RegWeight &) = default; | 522 RegWeight(const RegWeight &) = default; | 
| 413 RegWeight &operator=(const RegWeight &) = default; | 523 RegWeight &operator=(const RegWeight &) = default; | 
| 414 constexpr static uint32_t Inf = ~0; /// Force regalloc to give a register | 524 constexpr static uint32_t Inf = ~0; /// Force regalloc to give a register | 
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 bool getIgnoreLiveness() const { return IgnoreLiveness; } | 637 bool getIgnoreLiveness() const { return IgnoreLiveness; } | 
| 528 | 638 | 
| 529 int32_t getStackOffset() const { return StackOffset; } | 639 int32_t getStackOffset() const { return StackOffset; } | 
| 530 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 640 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 
| 531 /// Returns the variable's stack offset in symbolic form, to improve | 641 /// Returns the variable's stack offset in symbolic form, to improve | 
| 532 /// readability in DecorateAsm mode. | 642 /// readability in DecorateAsm mode. | 
| 533 IceString getSymbolicStackOffset(const Cfg *Func) const { | 643 IceString getSymbolicStackOffset(const Cfg *Func) const { | 
| 534 return "lv$" + getName(Func); | 644 return "lv$" + getName(Func); | 
| 535 } | 645 } | 
| 536 | 646 | 
| 537 static constexpr int32_t NoRegister = -1; | 647 bool hasReg() const { return getRegNum() != RegNumT::NoRegister; } | 
| 538 bool hasReg() const { return getRegNum() != NoRegister; } | 648 RegNumT getRegNum() const { return RegNum; } | 
| 539 int32_t getRegNum() const { return RegNum; } | 649 void setRegNum(RegNumT NewRegNum) { | 
| 540 void setRegNum(int32_t NewRegNum) { | |
| 541 // Regnum shouldn't be set more than once. | 650 // Regnum shouldn't be set more than once. | 
| 542 assert(!hasReg() || RegNum == NewRegNum); | 651 assert(!hasReg() || RegNum == NewRegNum); | 
| 543 RegNum = NewRegNum; | 652 RegNum = NewRegNum; | 
| 544 } | 653 } | 
| 545 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } | 654 bool hasRegTmp() const { return getRegNumTmp() != RegNumT::NoRegister; } | 
| 546 int32_t getRegNumTmp() const { return RegNumTmp; } | 655 RegNumT getRegNumTmp() const { return RegNumTmp; } | 
| 547 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } | 656 void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; } | 
| 548 | 657 | 
| 549 RegWeight getWeight(const Cfg *Func) const; | 658 RegWeight getWeight(const Cfg *Func) const; | 
| 550 | 659 | 
| 551 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; } | 660 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; } | 
| 552 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; } | 661 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; } | 
| 553 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; } | 662 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; } | 
| 554 bool mustNotHaveReg() const { | 663 bool mustNotHaveReg() const { | 
| 555 return RegRequirement == RR_MustNotHaveRegister; | 664 return RegRequirement == RR_MustNotHaveRegister; | 
| 556 } | 665 } | 
| 557 void setRematerializable(int32_t NewRegNum, int32_t NewOffset) { | 666 void setRematerializable(RegNumT NewRegNum, int32_t NewOffset) { | 
| 558 IsRematerializable = true; | 667 IsRematerializable = true; | 
| 559 setRegNum(NewRegNum); | 668 setRegNum(NewRegNum); | 
| 560 setStackOffset(NewOffset); | 669 setStackOffset(NewOffset); | 
| 561 setMustHaveReg(); | 670 setMustHaveReg(); | 
| 562 } | 671 } | 
| 563 bool isRematerializable() const { return IsRematerializable; } | 672 bool isRematerializable() const { return IsRematerializable; } | 
| 564 | 673 | 
| 565 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); } | 674 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); } | 
| 566 RegClass getRegClass() const { return RegisterClass; } | 675 RegClass getRegClass() const { return RegisterClass; } | 
| 567 | 676 | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 586 constexpr bool UseTrimmed = true; | 695 constexpr bool UseTrimmed = true; | 
| 587 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 696 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 
| 588 } | 697 } | 
| 589 | 698 | 
| 590 /// Creates a temporary copy of the variable with a different type. Used | 699 /// Creates a temporary copy of the variable with a different type. Used | 
| 591 /// primarily for syntactic correctness of textual assembly emission. Note | 700 /// primarily for syntactic correctness of textual assembly emission. Note | 
| 592 /// that only basic information is copied, in particular not IsArgument, | 701 /// that only basic information is copied, in particular not IsArgument, | 
| 593 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, | 702 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, | 
| 594 /// VarsReal. If NewRegNum!=NoRegister, then that register assignment is made | 703 /// VarsReal. If NewRegNum!=NoRegister, then that register assignment is made | 
| 595 /// instead of copying the existing assignment. | 704 /// instead of copying the existing assignment. | 
| 596 const Variable *asType(Type Ty, int32_t NewRegNum) const; | 705 const Variable *asType(Type Ty, RegNumT NewRegNum) const; | 
| 597 | 706 | 
| 598 void emit(const Cfg *Func) const override; | 707 void emit(const Cfg *Func) const override; | 
| 599 using Operand::dump; | 708 using Operand::dump; | 
| 600 void dump(const Cfg *Func, Ostream &Str) const override; | 709 void dump(const Cfg *Func, Ostream &Str) const override; | 
| 601 | 710 | 
| 602 /// Return reg num of base register, if different from stack/frame register. | 711 /// Return reg num of base register, if different from stack/frame register. | 
| 603 virtual int32_t getBaseRegNum() const { return NoRegister; } | 712 virtual RegNumT getBaseRegNum() const { return RegNumT::NoRegister; } | 
| 604 | 713 | 
| 605 static bool classof(const Operand *Operand) { | 714 static bool classof(const Operand *Operand) { | 
| 606 OperandKind Kind = Operand->getKind(); | 715 OperandKind Kind = Operand->getKind(); | 
| 607 return Kind >= kVariable && Kind <= kVariable_Max; | 716 return Kind >= kVariable && Kind <= kVariable_Max; | 
| 608 } | 717 } | 
| 609 | 718 | 
| 610 protected: | 719 protected: | 
| 611 Variable(OperandKind K, Type Ty, SizeT Index) | 720 Variable(OperandKind K, Type Ty, SizeT Index) | 
| 612 : Operand(K, Ty), Number(Index), | 721 : Operand(K, Ty), Number(Index), | 
| 613 RegisterClass(static_cast<RegClass>(Ty)) { | 722 RegisterClass(static_cast<RegClass>(Ty)) { | 
| (...skipping 11 matching lines...) Expand all Loading... | |
| 625 /// and validating live ranges. This is usually reserved for the stack | 734 /// and validating live ranges. This is usually reserved for the stack | 
| 626 /// pointer and other physical registers specifically referenced by name. | 735 /// pointer and other physical registers specifically referenced by name. | 
| 627 bool IgnoreLiveness = false; | 736 bool IgnoreLiveness = false; | 
| 628 // If IsRematerializable, RegNum keeps track of which register (stack or frame | 737 // If IsRematerializable, RegNum keeps track of which register (stack or frame | 
| 629 // pointer), and StackOffset is the known offset from that register. | 738 // pointer), and StackOffset is the known offset from that register. | 
| 630 bool IsRematerializable = false; | 739 bool IsRematerializable = false; | 
| 631 RegRequirement RegRequirement = RR_MayHaveRegister; | 740 RegRequirement RegRequirement = RR_MayHaveRegister; | 
| 632 RegClass RegisterClass; | 741 RegClass RegisterClass; | 
| 633 /// RegNum is the allocated register, or NoRegister if it isn't | 742 /// RegNum is the allocated register, or NoRegister if it isn't | 
| 634 /// register-allocated. | 743 /// register-allocated. | 
| 635 int32_t RegNum = NoRegister; | 744 RegNumT RegNum = RegNumT::NoRegister; | 
| 636 /// RegNumTmp is the tentative assignment during register allocation. | 745 /// RegNumTmp is the tentative assignment during register allocation. | 
| 637 int32_t RegNumTmp = NoRegister; | 746 RegNumT RegNumTmp = RegNumT::NoRegister; | 
| 638 /// StackOffset is the canonical location on stack (only if | 747 /// StackOffset is the canonical location on stack (only if | 
| 639 /// RegNum==NoRegister || IsArgument). | 748 /// RegNum==NoRegister || IsArgument). | 
| 640 int32_t StackOffset = 0; | 749 int32_t StackOffset = 0; | 
| 641 LiveRange Live; | 750 LiveRange Live; | 
| 642 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. | 751 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. | 
| 643 Variable *VarsReal[1]; | 752 Variable *VarsReal[1]; | 
| 644 }; | 753 }; | 
| 645 | 754 | 
| 646 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In | 755 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In | 
| 647 // this situation the variable must be split into a low and a high word. | 756 // this situation the variable must be split into a low and a high word. | 
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 812 private: | 921 private: | 
| 813 const Cfg *Func; | 922 const Cfg *Func; | 
| 814 MetadataKind Kind; | 923 MetadataKind Kind; | 
| 815 CfgVector<VariableTracking> Metadata; | 924 CfgVector<VariableTracking> Metadata; | 
| 816 const static InstDefList NoDefinitions; | 925 const static InstDefList NoDefinitions; | 
| 817 }; | 926 }; | 
| 818 | 927 | 
| 819 } // end of namespace Ice | 928 } // end of namespace Ice | 
| 820 | 929 | 
| 821 #endif // SUBZERO_SRC_ICEOPERAND_H | 930 #endif // SUBZERO_SRC_ICEOPERAND_H | 
| OLD | NEW |