Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(479)

Side by Side Diff: src/IceOperand.h

Issue 1676123002: Subzero: Use a proper RegNumT type instead of int32_t/SizeT. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Make it possible to do "auto NewReg = RegNumT::NoRegister;" Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceInstX86BaseImpl.h ('k') | src/IceOperand.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 NoRegisterValue. Note that
425 /// the ctor already does the target-specific limit check.
426 void assertIsValid() const { assert(Value != NoRegisterValue); }
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 NoRegisterValue as an enum value so that it can be used as an
442 // argument for the public ctor if desired.
443 enum { NoRegisterValue = std::numeric_limits<BaseType>::max() };
444 const static RegNumT NoRegister /* = NoRegisterValue */;
445
446 private:
447 BaseType Value = NoRegisterValue;
448 static BaseType Limit;
449 /// Private ctor called only by fromInt() and fixme().
450 RegNumT(BaseType Value) : Value(Value) { validate(Value); }
451 /// The ctor calls this to validate against the target-supplied limit.
452 static void validate(BaseType Value) {
453 (void)Value;
454 assert(Value == NoRegisterValue || Value < Limit);
455 }
456 /// Disallow operators that inappropriately make assumptions about register
457 /// enum value ordering.
458 bool operator<(const RegNumT &) = delete;
459 bool operator<=(const RegNumT &) = delete;
460 bool operator>(const RegNumT &) = delete;
461 bool operator>=(const RegNumT &) = delete;
462 };
463
464 /// RegNumBVIter wraps llvm::SmallBitVector so that instead of this pattern:
465 ///
466 /// for (int i = V.find_first(); i != -1; i = V.find_next(i)) {
467 /// RegNumT RegNum = RegNumT::fromInt(i);
468 /// ...
469 /// }
470 ///
471 /// this cleaner pattern can be used:
472 ///
473 /// for (RegNumT RegNum : RegNumBVIter(V)) {
474 /// ...
475 /// }
476 class RegNumBVIter {
477 using T = llvm::SmallBitVector;
478 static constexpr int Sentinel = -1;
479 RegNumBVIter() = delete;
480 RegNumBVIter(const RegNumBVIter &) = delete;
481 RegNumBVIter &operator=(const RegNumBVIter &) = delete;
482
483 public:
484 class Iterator {
485 Iterator() = delete;
486 Iterator &operator=(const Iterator &) = delete;
487
488 public:
489 explicit Iterator(const T &V) : V(V), Current(V.find_first()) {}
490 Iterator(const T &V, int Value) : V(V), Current(Value) {}
491 Iterator(const Iterator &) = default;
492 RegNumT operator*() {
493 assert(Current != Sentinel);
494 return RegNumT::fromInt(Current);
495 }
496 Iterator &operator++() {
497 assert(Current != Sentinel);
498 Current = V.find_next(Current);
499 return *this;
500 }
501 bool operator!=(Iterator &Other) { return Current != Other.Current; }
502
503 private:
504 const T &V;
505 int Current;
506 };
507
508 explicit RegNumBVIter(const T &V) : V(V) {}
509 Iterator begin() { return Iterator(V); }
510 Iterator end() { return Iterator(V, Sentinel); }
511
512 private:
513 const T &V;
514 };
515
405 /// RegWeight is a wrapper for a uint32_t weight value, with a special value 516 /// 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 517 /// that represents infinite weight, and an addWeight() method that ensures that
407 /// W+infinity=infinity. 518 /// W+infinity=infinity.
408 class RegWeight { 519 class RegWeight {
409 public: 520 public:
521 using BaseType = uint32_t;
410 RegWeight() = default; 522 RegWeight() = default;
411 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} 523 explicit RegWeight(BaseType Weight) : Weight(Weight) {}
412 RegWeight(const RegWeight &) = default; 524 RegWeight(const RegWeight &) = default;
413 RegWeight &operator=(const RegWeight &) = default; 525 RegWeight &operator=(const RegWeight &) = default;
414 constexpr static uint32_t Inf = ~0; /// Force regalloc to give a register 526 constexpr static BaseType Inf = ~0; /// Force regalloc to give a register
415 constexpr static uint32_t Zero = 0; /// Force regalloc NOT to give a register 527 constexpr static BaseType Zero = 0; /// Force regalloc NOT to give a register
416 constexpr static uint32_t Max = Inf - 1; /// Max natural weight. 528 constexpr static BaseType Max = Inf - 1; /// Max natural weight.
417 void addWeight(uint32_t Delta) { 529 void addWeight(BaseType Delta) {
418 if (Delta == Inf) 530 if (Delta == Inf)
419 Weight = Inf; 531 Weight = Inf;
420 else if (Weight != Inf) 532 else if (Weight != Inf)
421 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf) 533 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf)
422 Weight = Max; 534 Weight = Max;
423 } 535 }
424 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } 536 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
425 void setWeight(uint32_t Val) { Weight = Val; } 537 void setWeight(BaseType Val) { Weight = Val; }
426 uint32_t getWeight() const { return Weight; } 538 BaseType getWeight() const { return Weight; }
427 539
428 private: 540 private:
429 uint32_t Weight = 0; 541 BaseType Weight = 0;
430 }; 542 };
431 Ostream &operator<<(Ostream &Str, const RegWeight &W); 543 Ostream &operator<<(Ostream &Str, const RegWeight &W);
432 bool operator<(const RegWeight &A, const RegWeight &B); 544 bool operator<(const RegWeight &A, const RegWeight &B);
433 bool operator<=(const RegWeight &A, const RegWeight &B); 545 bool operator<=(const RegWeight &A, const RegWeight &B);
434 bool operator==(const RegWeight &A, const RegWeight &B); 546 bool operator==(const RegWeight &A, const RegWeight &B);
435 547
436 /// LiveRange is a set of instruction number intervals representing a variable's 548 /// LiveRange is a set of instruction number intervals representing a variable's
437 /// live range. Generally there is one interval per basic block where the 549 /// live range. Generally there is one interval per basic block where the
438 /// variable is live, but adjacent intervals get coalesced into a single 550 /// variable is live, but adjacent intervals get coalesced into a single
439 /// interval. 551 /// interval.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 bool getIgnoreLiveness() const { return IgnoreLiveness; } 639 bool getIgnoreLiveness() const { return IgnoreLiveness; }
528 640
529 int32_t getStackOffset() const { return StackOffset; } 641 int32_t getStackOffset() const { return StackOffset; }
530 void setStackOffset(int32_t Offset) { StackOffset = Offset; } 642 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
531 /// Returns the variable's stack offset in symbolic form, to improve 643 /// Returns the variable's stack offset in symbolic form, to improve
532 /// readability in DecorateAsm mode. 644 /// readability in DecorateAsm mode.
533 IceString getSymbolicStackOffset(const Cfg *Func) const { 645 IceString getSymbolicStackOffset(const Cfg *Func) const {
534 return "lv$" + getName(Func); 646 return "lv$" + getName(Func);
535 } 647 }
536 648
537 static constexpr int32_t NoRegister = -1; 649 bool hasReg() const { return getRegNum() != RegNumT::NoRegister; }
538 bool hasReg() const { return getRegNum() != NoRegister; } 650 RegNumT getRegNum() const { return RegNum; }
539 int32_t getRegNum() const { return RegNum; } 651 void setRegNum(RegNumT NewRegNum) {
540 void setRegNum(int32_t NewRegNum) {
541 // Regnum shouldn't be set more than once. 652 // Regnum shouldn't be set more than once.
542 assert(!hasReg() || RegNum == NewRegNum); 653 assert(!hasReg() || RegNum == NewRegNum);
543 RegNum = NewRegNum; 654 RegNum = NewRegNum;
544 } 655 }
545 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } 656 bool hasRegTmp() const { return getRegNumTmp() != RegNumT::NoRegister; }
546 int32_t getRegNumTmp() const { return RegNumTmp; } 657 RegNumT getRegNumTmp() const { return RegNumTmp; }
547 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } 658 void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; }
548 659
549 RegWeight getWeight(const Cfg *Func) const; 660 RegWeight getWeight(const Cfg *Func) const;
550 661
551 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; } 662 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
552 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; } 663 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
553 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; } 664 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
554 bool mustNotHaveReg() const { 665 bool mustNotHaveReg() const {
555 return RegRequirement == RR_MustNotHaveRegister; 666 return RegRequirement == RR_MustNotHaveRegister;
556 } 667 }
557 void setRematerializable(int32_t NewRegNum, int32_t NewOffset) { 668 void setRematerializable(RegNumT NewRegNum, int32_t NewOffset) {
558 IsRematerializable = true; 669 IsRematerializable = true;
559 setRegNum(NewRegNum); 670 setRegNum(NewRegNum);
560 setStackOffset(NewOffset); 671 setStackOffset(NewOffset);
561 setMustHaveReg(); 672 setMustHaveReg();
562 } 673 }
563 bool isRematerializable() const { return IsRematerializable; } 674 bool isRematerializable() const { return IsRematerializable; }
564 675
565 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); } 676 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); }
566 RegClass getRegClass() const { return RegisterClass; } 677 RegClass getRegClass() const { return RegisterClass; }
567 678
(...skipping 18 matching lines...) Expand all
586 constexpr bool UseTrimmed = true; 697 constexpr bool UseTrimmed = true;
587 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); 698 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
588 } 699 }
589 700
590 /// Creates a temporary copy of the variable with a different type. Used 701 /// Creates a temporary copy of the variable with a different type. Used
591 /// primarily for syntactic correctness of textual assembly emission. Note 702 /// primarily for syntactic correctness of textual assembly emission. Note
592 /// that only basic information is copied, in particular not IsArgument, 703 /// that only basic information is copied, in particular not IsArgument,
593 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, 704 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
594 /// VarsReal. If NewRegNum!=NoRegister, then that register assignment is made 705 /// VarsReal. If NewRegNum!=NoRegister, then that register assignment is made
595 /// instead of copying the existing assignment. 706 /// instead of copying the existing assignment.
596 const Variable *asType(Type Ty, int32_t NewRegNum) const; 707 const Variable *asType(Type Ty, RegNumT NewRegNum) const;
597 708
598 void emit(const Cfg *Func) const override; 709 void emit(const Cfg *Func) const override;
599 using Operand::dump; 710 using Operand::dump;
600 void dump(const Cfg *Func, Ostream &Str) const override; 711 void dump(const Cfg *Func, Ostream &Str) const override;
601 712
602 /// Return reg num of base register, if different from stack/frame register. 713 /// Return reg num of base register, if different from stack/frame register.
603 virtual int32_t getBaseRegNum() const { return NoRegister; } 714 virtual RegNumT getBaseRegNum() const { return RegNumT::NoRegister; }
604 715
605 static bool classof(const Operand *Operand) { 716 static bool classof(const Operand *Operand) {
606 OperandKind Kind = Operand->getKind(); 717 OperandKind Kind = Operand->getKind();
607 return Kind >= kVariable && Kind <= kVariable_Max; 718 return Kind >= kVariable && Kind <= kVariable_Max;
608 } 719 }
609 720
610 protected: 721 protected:
611 Variable(OperandKind K, Type Ty, SizeT Index) 722 Variable(OperandKind K, Type Ty, SizeT Index)
612 : Operand(K, Ty), Number(Index), 723 : Operand(K, Ty), Number(Index),
613 RegisterClass(static_cast<RegClass>(Ty)) { 724 RegisterClass(static_cast<RegClass>(Ty)) {
(...skipping 11 matching lines...) Expand all
625 /// and validating live ranges. This is usually reserved for the stack 736 /// and validating live ranges. This is usually reserved for the stack
626 /// pointer and other physical registers specifically referenced by name. 737 /// pointer and other physical registers specifically referenced by name.
627 bool IgnoreLiveness = false; 738 bool IgnoreLiveness = false;
628 // If IsRematerializable, RegNum keeps track of which register (stack or frame 739 // If IsRematerializable, RegNum keeps track of which register (stack or frame
629 // pointer), and StackOffset is the known offset from that register. 740 // pointer), and StackOffset is the known offset from that register.
630 bool IsRematerializable = false; 741 bool IsRematerializable = false;
631 RegRequirement RegRequirement = RR_MayHaveRegister; 742 RegRequirement RegRequirement = RR_MayHaveRegister;
632 RegClass RegisterClass; 743 RegClass RegisterClass;
633 /// RegNum is the allocated register, or NoRegister if it isn't 744 /// RegNum is the allocated register, or NoRegister if it isn't
634 /// register-allocated. 745 /// register-allocated.
635 int32_t RegNum = NoRegister; 746 RegNumT RegNum = RegNumT::NoRegister;
636 /// RegNumTmp is the tentative assignment during register allocation. 747 /// RegNumTmp is the tentative assignment during register allocation.
637 int32_t RegNumTmp = NoRegister; 748 RegNumT RegNumTmp = RegNumT::NoRegister;
638 /// StackOffset is the canonical location on stack (only if 749 /// StackOffset is the canonical location on stack (only if
639 /// RegNum==NoRegister || IsArgument). 750 /// RegNum==NoRegister || IsArgument).
640 int32_t StackOffset = 0; 751 int32_t StackOffset = 0;
641 LiveRange Live; 752 LiveRange Live;
642 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. 753 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
643 Variable *VarsReal[1]; 754 Variable *VarsReal[1];
644 }; 755 };
645 756
646 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In 757 // 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. 758 // 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
812 private: 923 private:
813 const Cfg *Func; 924 const Cfg *Func;
814 MetadataKind Kind; 925 MetadataKind Kind;
815 CfgVector<VariableTracking> Metadata; 926 CfgVector<VariableTracking> Metadata;
816 const static InstDefList NoDefinitions; 927 const static InstDefList NoDefinitions;
817 }; 928 };
818 929
819 } // end of namespace Ice 930 } // end of namespace Ice
820 931
821 #endif // SUBZERO_SRC_ICEOPERAND_H 932 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW
« no previous file with comments | « src/IceInstX86BaseImpl.h ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698