OSDN Git Service

Subzero: Use a proper RegNumT type instead of int32_t/SizeT.
authorJim Stichnoth <stichnot@chromium.org>
Wed, 10 Feb 2016 19:20:30 +0000 (11:20 -0800)
committerJim Stichnoth <stichnot@chromium.org>
Wed, 10 Feb 2016 19:20:30 +0000 (11:20 -0800)
Originally, register numbers were represented explicitly as int32_t, particularly so that -1 (or negative values in general) could be used as a NoRegister sentinel value.  This created two problems:

1. It would be better to use a unique name for the type, to distinguish from other explicit int32_t uses such as stack offsets.

2. Apart from NoRegister, register number values ultimately come from unsigned sources like enum values and bitvector positions.  This results in a number of clumsy casts to remove compiler warnings.

This creates a simple RegNumT class to manage this.  It also deletes ordered comparison operators to help catch errors where particular register number orderings are assumed (as opposed to orderings of the encoded register values).

In addition, it creates a RegNumBitVector wrapper class that makes it much cleaner to do range-based for loops over bit vectors that represent RegNumT sets.

BUG= none
R=eholk@chromium.org, jpp@chromium.org

Review URL: https://codereview.chromium.org/1676123002 .

27 files changed:
src/IceAssemblerARM32.cpp
src/IceAssemblerARM32.h
src/IceCfgNode.cpp
src/IceInstARM32.cpp
src/IceInstARM32.h
src/IceInstX8632.cpp
src/IceInstX8664.cpp
src/IceInstX86Base.h
src/IceInstX86BaseImpl.h
src/IceOperand.cpp
src/IceOperand.h
src/IceRegAlloc.cpp
src/IceRegAlloc.h
src/IceRegistersARM32.h
src/IceRegistersMIPS32.h
src/IceRegistersX8632.h
src/IceTargetLowering.cpp
src/IceTargetLowering.h
src/IceTargetLoweringARM32.cpp
src/IceTargetLoweringARM32.h
src/IceTargetLoweringMIPS32.cpp
src/IceTargetLoweringMIPS32.h
src/IceTargetLoweringX8632Traits.h
src/IceTargetLoweringX8664.cpp
src/IceTargetLoweringX8664Traits.h
src/IceTargetLoweringX86Base.h
src/IceTargetLoweringX86BaseImpl.h

index 89854b1..ba328c8 100644 (file)
@@ -195,7 +195,7 @@ RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
 
 IValueT getEncodedGPRegNum(const Variable *Var) {
   assert(Var->hasReg());
-  int32_t Reg = Var->getRegNum();
+  const auto Reg = Var->getRegNum();
   return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
                                         : RegARM32::getEncodedGPR(Reg);
 }
@@ -470,9 +470,8 @@ EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value,
     IOffsetT Offset = Var->getStackOffset();
     if (!Utils::IsAbsoluteUint(12, Offset))
       return CantEncode;
-    int32_t BaseRegNum = Var->getBaseRegNum();
-    if (BaseRegNum == Variable::NoRegister)
-      BaseRegNum = TInfo.FrameOrStackReg;
+    const auto BaseRegNum =
+        Var->hasReg() ? Var->getBaseRegNum() : TInfo.FrameOrStackReg;
     Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset,
                                OperandARM32Mem::Offset);
     return EncodedAsImmRegOffset;
@@ -585,7 +584,7 @@ void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags,
     return;
   if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc))
     llvm::report_fatal_error(std::string(InstName) + ": " +
-                             RegARM32::getRegName(Reg) +
+                             RegARM32::getRegName(RegARM32::Reg_pc) +
                              "=pc not allowed when CC=1");
 }
 
@@ -602,7 +601,7 @@ size_t MoveRelocatableFixup::emit(GlobalContext *Ctx,
   IValueT Inst = Asm.load<IValueT>(position());
   Str << "\t"
          "mov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t"
-      << RegARM32::getRegName((Inst >> kRdShift) & 0xF)
+      << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF))
       << ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper")
       << "16:" << symbol(Ctx, &Asm) << "\t@ .word "
       << llvm::format_hex_no_prefix(Inst, 8) << "\n";
index acef261..3e6d5a3 100644 (file)
@@ -86,13 +86,13 @@ public:
     TargetInfo &operator=(const TargetInfo &) = delete;
 
   public:
-    TargetInfo(bool HasFramePointer, SizeT FrameOrStackReg)
+    TargetInfo(bool HasFramePointer, RegNumT FrameOrStackReg)
         : HasFramePointer(HasFramePointer), FrameOrStackReg(FrameOrStackReg) {}
     explicit TargetInfo(const TargetLowering *Target)
         : HasFramePointer(Target->hasFramePointer()),
           FrameOrStackReg(Target->getFrameOrStackReg()) {}
     const bool HasFramePointer;
-    const SizeT FrameOrStackReg;
+    const RegNumT FrameOrStackReg;
   };
 
   explicit AssemblerARM32(bool use_far_branches = false)
index 647da89..9dbe7df 100644 (file)
@@ -338,8 +338,8 @@ bool sameVarOrReg(TargetLowering *Target, const Variable *Var1,
   if (!Var2->hasReg())
     return false;
 
-  int32_t RegNum1 = Var1->getRegNum();
-  int32_t RegNum2 = Var2->getRegNum();
+  const auto RegNum1 = Var1->getRegNum();
+  const auto RegNum2 = Var2->getRegNum();
   // Quick common-case check.
   if (RegNum1 == RegNum2)
     return true;
@@ -920,8 +920,8 @@ void emitRegisterUsage(Ostream &Str, const Cfg *Func, const CfgNode *Node,
     return;
   Liveness *Liveness = Func->getLiveness();
   const LivenessBV *Live;
-  const int32_t StackReg = Func->getTarget()->getStackReg();
-  const int32_t FrameOrStackReg = Func->getTarget()->getFrameOrStackReg();
+  const auto StackReg = Func->getTarget()->getStackReg();
+  const auto FrameOrStackReg = Func->getTarget()->getFrameOrStackReg();
   if (IsLiveIn) {
     Live = &Liveness->getLiveIn(Node);
     Str << "\t\t\t\t/* LiveIn=";
@@ -937,7 +937,7 @@ void emitRegisterUsage(Ostream &Str, const Cfg *Func, const CfgNode *Node,
       Variable *Var = Liveness->getVariable(i, Node);
       if (!Var->hasReg())
         continue;
-      const int32_t RegNum = Var->getRegNum();
+      const auto RegNum = Var->getRegNum();
       if (RegNum == StackReg || RegNum == FrameOrStackReg)
         continue;
       if (IsLiveIn)
@@ -948,7 +948,7 @@ void emitRegisterUsage(Ostream &Str, const Cfg *Func, const CfgNode *Node,
     // order.
     std::sort(LiveRegs.begin(), LiveRegs.end(),
               [](const Variable *V1, const Variable *V2) {
-                return V1->getRegNum() < V2->getRegNum();
+                return unsigned(V1->getRegNum()) < unsigned(V2->getRegNum());
               });
     bool First = true;
     for (Variable *Var : LiveRegs) {
index 600658c..9c5e4e5 100644 (file)
@@ -888,13 +888,13 @@ void InstARM32RegisterStackOp::emitSRegsAsText(const Cfg *Func,
   Ostream &Str = Func->getContext()->getStrEmit();
   Str << "\t" << getSRegOpcode() << "\t{";
   bool IsFirst = true;
-  int32_t Base = BaseReg->getRegNum();
+  const auto Base = BaseReg->getRegNum();
   for (SizeT i = 0; i < RegCount; ++i) {
     if (IsFirst)
       IsFirst = false;
     else
       Str << ", ";
-    Str << RegARM32::getRegName(Base + i);
+    Str << RegARM32::getRegName(RegNumT::fixme(Base + i));
   }
   Str << "}";
 }
@@ -914,8 +914,9 @@ namespace {
 
 bool isAssignedConsecutiveRegisters(const Variable *Before,
                                     const Variable *After) {
-  return RegARM32::getEncodedSReg(Before->getRegNum()) + 1 ==
-         RegARM32::getEncodedSReg(After->getRegNum());
+  assert(Before->hasReg());
+  assert(After->hasReg());
+  return RegNumT::fixme(Before->getRegNum() + 1) == After->getRegNum();
 }
 
 } // end of anonymous namespace
@@ -934,7 +935,8 @@ void InstARM32RegisterStackOp::emitUsingForm(const Cfg *Func,
     for (SizeT i = 0; i < NumRegs; ++i) {
       const Variable *Var = getStackReg(i);
       assert(Var->hasReg() && "stack op only applies to registers");
-      int32_t Reg = RegARM32::getEncodedGPR(Var->getRegNum());
+      const RegARM32::GPRRegister Reg =
+          RegARM32::getEncodedGPR(Var->getRegNum());
       LastDest = Var;
       GPRegisters |= (1 << Reg);
       ++IntegerCount;
@@ -1069,7 +1071,7 @@ InstARM32Mov::InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
 // register that this instruction is accessing.
 Register getDRegister(const Variable *Src, uint32_t Index) {
   assert(Src->hasReg());
-  const auto SrcReg = static_cast<Register>(Src->getRegNum());
+  const auto SrcReg = Src->getRegNum();
 
   const RegARM32::RegTableType &SrcEntry = RegARM32::RegTable[SrcReg];
   assert(SrcEntry.IsVec128);
@@ -1107,7 +1109,7 @@ constexpr uint32_t getDIndex(uint32_t NumElements, uint32_t Index) {
 // directly from an S register. This function finds the right one.
 Register getSRegister(const Variable *Src, uint32_t Index) {
   assert(Src->hasReg());
-  const auto SrcReg = static_cast<Register>(Src->getRegNum());
+  const auto SrcReg = Src->getRegNum();
 
   // For floating point values, we need to be allocated to Q0 - Q7, so we can
   // directly access the value we want as one of the S registers.
index 4d8f02b..40518c1 100644 (file)
@@ -354,14 +354,14 @@ public:
   static bool classof(const Operand *Operand) {
     return Operand->getKind() == StackVariableKind;
   }
-  void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; }
-  int32_t getBaseRegNum() const override { return BaseRegNum; }
+  void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
+  RegNumT getBaseRegNum() const override { return BaseRegNum; }
   // Inherit dump() and emit() from Variable.
 
 private:
   StackVariable(Type Ty, SizeT Index)
       : Variable(StackVariableKind, Ty, Index) {}
-  int32_t BaseRegNum = Variable::NoRegister;
+  RegNumT BaseRegNum = RegNumT::NoRegister;
 };
 
 /// Base class for ARM instructions. While most ARM instructions can be
index 24f6c2b..5d081e0 100644 (file)
@@ -99,10 +99,10 @@ TargetX8632Traits::X86OperandMem::X86OperandMem(
 
 namespace {
 
-int32_t GetRematerializableOffset(Variable *Var,
+int32_t getRematerializableOffset(Variable *Var,
                                   const Ice::X8632::TargetX8632 *Target) {
   int32_t Disp = Var->getStackOffset();
-  SizeT RegNum = static_cast<SizeT>(Var->getRegNum());
+  const auto RegNum = Var->getRegNum();
   if (RegNum == Target->getFrameReg()) {
     Disp += Target->getFrameFixedAllocaOffset();
   } else if (RegNum != Target->getStackReg()) {
@@ -139,7 +139,7 @@ void TargetX8632Traits::X86OperandMem::emit(const Cfg *Func) const {
   // physical register (esp or ebp), and update the Offset.
   int32_t Disp = 0;
   if (getBase() && getBase()->isRematerializable()) {
-    Disp += GetRematerializableOffset(getBase(), Target);
+    Disp += getRematerializableOffset(getBase(), Target);
   }
   // The index should never be rematerializable.  But if we ever allow it, then
   // we should make sure the rematerialization offset is shifted by the Shift
@@ -199,7 +199,7 @@ void TargetX8632Traits::X86OperandMem::dump(const Cfg *Func,
   const auto *Target =
       static_cast<const ::Ice::X8632::TargetX8632 *>(Func->getTarget());
   if (getBase() && getBase()->isRematerializable()) {
-    Disp += GetRematerializableOffset(getBase(), Target);
+    Disp += getRematerializableOffset(getBase(), Target);
   }
   if (getBase()) {
     if (Func)
@@ -267,7 +267,7 @@ TargetX8632Traits::Address TargetX8632Traits::X86OperandMem::toAsmAddress(
   validateMemOperandPIC(this, UseNonsfi);
   int32_t Disp = 0;
   if (getBase() && getBase()->isRematerializable()) {
-    Disp += GetRematerializableOffset(getBase(), Target);
+    Disp += getRematerializableOffset(getBase(), Target);
   }
   // The index should never be rematerializable.  But if we ever allow it, then
   // we should make sure the rematerialization offset is shifted by the Shift
index ca2acfa..bbcb080 100644 (file)
@@ -89,11 +89,10 @@ TargetX8664Traits::X86OperandMem::X86OperandMem(Cfg *Func, Type Ty,
 }
 
 namespace {
-static int32_t
-getRematerializableOffset(Variable *Var,
-                          const ::Ice::X8664::TargetX8664 *Target) {
+int32_t getRematerializableOffset(Variable *Var,
+                                  const ::Ice::X8664::TargetX8664 *Target) {
   int32_t Disp = Var->getStackOffset();
-  SizeT RegNum = static_cast<SizeT>(Var->getRegNum());
+  const auto RegNum = Var->getRegNum();
   if (RegNum == Target->getFrameReg()) {
     Disp += Target->getFrameFixedAllocaOffset();
   } else if (RegNum != Target->getStackReg()) {
index 5cfdfa6..42e1558 100644 (file)
@@ -499,15 +499,15 @@ template <typename TraitsType> struct InstImpl {
                                     const Operand *Src2Op,
                                     const GPREmitterShiftD &Emitter);
 
-  template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
-            SReg_t (*srcEnc)(int32_t)>
+  template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+            SReg_t (*srcEnc)(RegNumT)>
   static void emitIASCastRegOp(const Cfg *Func, Type DestTy,
                                const Variable *Dest, Type SrcTy,
                                const Operand *Src,
                                const CastEmitterRegOp<DReg_t, SReg_t> &Emitter);
 
-  template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
-            SReg_t (*srcEnc)(int32_t)>
+  template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+            SReg_t (*srcEnc)(RegNumT)>
   static void
   emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy, const Variable *Dest,
                        const Operand *Src0, const Operand *Src1,
@@ -1045,8 +1045,8 @@ template <typename TraitsType> struct InstImpl {
           //   mov ch, ebp ==> not redundant due to different base registers
           //   mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting
           //                    is handled by Inst86Zext.
-          const int32_t SrcReg = SrcVar->getRegNum();
-          const int32_t DestReg = this->Dest->getRegNum();
+          const auto SrcReg = SrcVar->getRegNum();
+          const auto DestReg = this->Dest->getRegNum();
           return (Traits::getEncoding(SrcReg) ==
                   Traits::getEncoding(DestReg)) &&
                  (Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg));
index 5c55bf3..6a087e8 100644 (file)
@@ -888,8 +888,8 @@ void InstImpl<TraitsType>::emitIASRegOpTyXMM(const Cfg *Func, Type Ty,
 }
 
 template <typename TraitsType>
-template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
-          SReg_t (*srcEnc)(int32_t)>
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+          SReg_t (*srcEnc)(RegNumT)>
 void InstImpl<TraitsType>::emitIASCastRegOp(
     const Cfg *Func, Type DestTy, const Variable *Dest, Type SrcTy,
     const Operand *Src, const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
@@ -915,8 +915,8 @@ void InstImpl<TraitsType>::emitIASCastRegOp(
 }
 
 template <typename TraitsType>
-template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
-          SReg_t (*srcEnc)(int32_t)>
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
+          SReg_t (*srcEnc)(RegNumT)>
 void InstImpl<TraitsType>::emitIASThreeOpImmOps(
     const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
     const Operand *Src1, const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
@@ -1191,8 +1191,8 @@ void InstImpl<TraitsType>::InstX86Cbwdq::emit(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrEmit();
   assert(this->getSrcSize() == 1);
   Operand *Src0 = this->getSrc(0);
-  int32_t DestReg = this->getDest()->getRegNum();
-  int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
+  const auto DestReg = this->getDest()->getRegNum();
+  const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
   (void)DestReg;
   (void)SrcReg;
   switch (Src0->getType()) {
@@ -1232,8 +1232,8 @@ void InstImpl<TraitsType>::InstX86Cbwdq::emitIAS(const Cfg *Func) const {
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(this->getSrcSize() == 1);
   Operand *Src0 = this->getSrc(0);
-  int32_t DestReg = this->getDest()->getRegNum();
-  int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
+  const auto DestReg = this->getDest()->getRegNum();
+  const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
   (void)DestReg;
   (void)SrcReg;
   switch (Src0->getType()) {
@@ -1987,7 +1987,7 @@ void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
     Type Ty = Src0Var->getType();
     // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
     // acceptable type.
-    Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister)
+    Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, RegNumT::NoRegister)
         ->emit(Func);
   } else {
     Src0->emit(Func);
@@ -2025,7 +2025,7 @@ void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const {
          InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
   const Operand *NewSrc = Src;
   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
-    int32_t NewRegNum = Variable::NoRegister;
+    auto NewRegNum = RegNumT::NoRegister;
     if (SrcVar->hasReg())
       NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
     if (SrcTy != DestTy)
@@ -2551,7 +2551,7 @@ void InstImpl<TraitsType>::InstX86Pinsr::emit(const Cfg *Func) const {
   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
     // If src1 is a register, it should always be r32.
     if (Src1Var->hasReg()) {
-      int32_t NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
+      const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
       const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum);
       NewSrc->emit(Func);
     } else {
@@ -2578,8 +2578,8 @@ void InstImpl<TraitsType>::InstX86Pinsr::emitIAS(const Cfg *Func) const {
   if (BuildDefs::asserts()) {
     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
       if (Src0Var->hasReg()) {
-        int32_t RegNum = Src0Var->getRegNum();
-        int32_t BaseRegNum = Traits::getBaseReg(RegNum);
+        const auto RegNum = Src0Var->getRegNum();
+        const auto BaseRegNum = Traits::getBaseReg(RegNum);
         (void)BaseRegNum;
         assert(Traits::getEncodedGPR(RegNum) ==
                Traits::getEncodedGPR(BaseRegNum));
index ff1de64..cc4e964 100644 (file)
@@ -86,6 +86,9 @@ bool operator==(const RelocatableTuple &A, const RelocatableTuple &B) {
   return true;
 }
 
+const RegNumT RegNumT::NoRegister(RegNumT::NoRegisterValue);
+RegNumT::BaseType RegNumT::Limit = 0;
+
 bool operator<(const RegWeight &A, const RegWeight &B) {
   return A.getWeight() < B.getWeight();
 }
@@ -190,7 +193,7 @@ IceString Variable::getName(const Cfg *Func) const {
   return "__" + std::to_string(getIndex());
 }
 
-const Variable *Variable::asType(Type Ty, int32_t NewRegNum) const {
+const Variable *Variable::asType(Type Ty, RegNumT NewRegNum) const {
   // Note: This returns a Variable, even if the "this" object is a subclass of
   // Variable.
   if (!BuildDefs::dump() || getType() == Ty)
@@ -198,7 +201,7 @@ const Variable *Variable::asType(Type Ty, int32_t NewRegNum) const {
   Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
       Variable(kVariable, Ty, Number);
   V->NameIndex = NameIndex;
-  V->RegNum = NewRegNum == NoRegister ? RegNum : NewRegNum;
+  V->RegNum = NewRegNum == RegNumT::NoRegister ? RegNum : NewRegNum;
   V->StackOffset = StackOffset;
   return V;
 }
@@ -511,9 +514,8 @@ void Variable::dump(const Cfg *Func, Ostream &Str) const {
   } else if (Func->getTarget()->hasComputedFrame()) {
     if (Func->isVerbose(IceV_RegOrigins))
       Str << ":";
-    int32_t BaseRegisterNumber = getBaseRegNum();
-    if (BaseRegisterNumber == NoRegister)
-      BaseRegisterNumber = Func->getTarget()->getFrameOrStackReg();
+    const auto BaseRegisterNumber =
+        hasReg() ? getBaseRegNum() : Func->getTarget()->getFrameOrStackReg();
     Str << "["
         << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
     int32_t Offset = getStackOffset();
index 91e9de0..a203086 100644 (file)
@@ -402,19 +402,131 @@ private:
   ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {}
 };
 
+/// RegNumT is for holding target-specific register numbers, plus the sentinel
+/// value NoRegister.  Its public ctor allows direct use of enum values, such as
+/// RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1).  This is to try to
+/// prevent inappropriate assumptions about enum ordering.  If needed, the
+/// fromInt() method can be used, such as when a RegNumT is based on a bitvector
+/// index.
+class RegNumT {
+public:
+  using BaseType = uint32_t;
+  RegNumT() = default;
+  RegNumT(const RegNumT &) = default;
+  template <typename AnyEnum>
+  RegNumT(AnyEnum Value,
+          typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0)
+      : Value(Value) {
+    validate(Value);
+  }
+  RegNumT &operator=(const RegNumT &) = default;
+  operator unsigned() const { return Value; }
+  /// Asserts that the register is valid, i.e. not NoRegisterValue.  Note that
+  /// the ctor already does the target-specific limit check.
+  void assertIsValid() const { assert(Value != NoRegisterValue); }
+  static RegNumT fromInt(BaseType Value) { return RegNumT(Value); }
+  /// Marks cases that inappropriately add/subtract RegNumT values, and
+  /// therefore need to be fixed because they make assumptions about register
+  /// enum value ordering.  TODO(stichnot): Remove fixme() as soon as all
+  /// current uses are fixed/removed.
+  static RegNumT fixme(BaseType Value) { return RegNumT(Value); }
+  /// The target's staticInit() method should call setLimit() to register the
+  /// upper bound of allowable values.
+  static void setLimit(BaseType Value) {
+    // Make sure it's only called once.
+    assert(Limit == 0);
+    assert(Value != 0);
+    Limit = Value;
+  }
+  // Define NoRegisterValue as an enum value so that it can be used as an
+  // argument for the public ctor if desired.
+  enum { NoRegisterValue = std::numeric_limits<BaseType>::max() };
+  const static RegNumT NoRegister /* = NoRegisterValue */;
+
+private:
+  BaseType Value = NoRegisterValue;
+  static BaseType Limit;
+  /// Private ctor called only by fromInt() and fixme().
+  RegNumT(BaseType Value) : Value(Value) { validate(Value); }
+  /// The ctor calls this to validate against the target-supplied limit.
+  static void validate(BaseType Value) {
+    (void)Value;
+    assert(Value == NoRegisterValue || Value < Limit);
+  }
+  /// Disallow operators that inappropriately make assumptions about register
+  /// enum value ordering.
+  bool operator<(const RegNumT &) = delete;
+  bool operator<=(const RegNumT &) = delete;
+  bool operator>(const RegNumT &) = delete;
+  bool operator>=(const RegNumT &) = delete;
+};
+
+/// RegNumBVIter wraps llvm::SmallBitVector so that instead of this pattern:
+///
+///   for (int i = V.find_first(); i != -1; i = V.find_next(i)) {
+///     RegNumT RegNum = RegNumT::fromInt(i);
+///     ...
+///   }
+///
+/// this cleaner pattern can be used:
+///
+///   for (RegNumT RegNum : RegNumBVIter(V)) {
+///     ...
+///   }
+class RegNumBVIter {
+  using T = llvm::SmallBitVector;
+  static constexpr int Sentinel = -1;
+  RegNumBVIter() = delete;
+  RegNumBVIter(const RegNumBVIter &) = delete;
+  RegNumBVIter &operator=(const RegNumBVIter &) = delete;
+
+public:
+  class Iterator {
+    Iterator() = delete;
+    Iterator &operator=(const Iterator &) = delete;
+
+  public:
+    explicit Iterator(const T &V) : V(V), Current(V.find_first()) {}
+    Iterator(const T &V, int Value) : V(V), Current(Value) {}
+    Iterator(const Iterator &) = default;
+    RegNumT operator*() {
+      assert(Current != Sentinel);
+      return RegNumT::fromInt(Current);
+    }
+    Iterator &operator++() {
+      assert(Current != Sentinel);
+      Current = V.find_next(Current);
+      return *this;
+    }
+    bool operator!=(Iterator &Other) { return Current != Other.Current; }
+
+  private:
+    const T &V;
+    int Current;
+  };
+
+  explicit RegNumBVIter(const T &V) : V(V) {}
+  Iterator begin() { return Iterator(V); }
+  Iterator end() { return Iterator(V, Sentinel); }
+
+private:
+  const T &V;
+};
+
 /// RegWeight is a wrapper for a uint32_t weight value, with a special value
 /// that represents infinite weight, and an addWeight() method that ensures that
 /// W+infinity=infinity.
 class RegWeight {
 public:
+  using BaseType = uint32_t;
   RegWeight() = default;
-  explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
+  explicit RegWeight(BaseType Weight) : Weight(Weight) {}
   RegWeight(const RegWeight &) = default;
   RegWeight &operator=(const RegWeight &) = default;
-  constexpr static uint32_t Inf = ~0; /// Force regalloc to give a register
-  constexpr static uint32_t Zero = 0; /// Force regalloc NOT to give a register
-  constexpr static uint32_t Max = Inf - 1; /// Max natural weight.
-  void addWeight(uint32_t Delta) {
+  constexpr static BaseType Inf = ~0; /// Force regalloc to give a register
+  constexpr static BaseType Zero = 0; /// Force regalloc NOT to give a register
+  constexpr static BaseType Max = Inf - 1; /// Max natural weight.
+  void addWeight(BaseType Delta) {
     if (Delta == Inf)
       Weight = Inf;
     else if (Weight != Inf)
@@ -422,11 +534,11 @@ public:
         Weight = Max;
   }
   void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
-  void setWeight(uint32_t Val) { Weight = Val; }
-  uint32_t getWeight() const { return Weight; }
+  void setWeight(BaseType Val) { Weight = Val; }
+  BaseType getWeight() const { return Weight; }
 
 private:
-  uint32_t Weight = 0;
+  BaseType Weight = 0;
 };
 Ostream &operator<<(Ostream &Str, const RegWeight &W);
 bool operator<(const RegWeight &A, const RegWeight &B);
@@ -534,17 +646,16 @@ public:
     return "lv$" + getName(Func);
   }
 
-  static constexpr int32_t NoRegister = -1;
-  bool hasReg() const { return getRegNum() != NoRegister; }
-  int32_t getRegNum() const { return RegNum; }
-  void setRegNum(int32_t NewRegNum) {
+  bool hasReg() const { return getRegNum() != RegNumT::NoRegister; }
+  RegNumT getRegNum() const { return RegNum; }
+  void setRegNum(RegNumT NewRegNum) {
     // Regnum shouldn't be set more than once.
     assert(!hasReg() || RegNum == NewRegNum);
     RegNum = NewRegNum;
   }
-  bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
-  int32_t getRegNumTmp() const { return RegNumTmp; }
-  void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
+  bool hasRegTmp() const { return getRegNumTmp() != RegNumT::NoRegister; }
+  RegNumT getRegNumTmp() const { return RegNumTmp; }
+  void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; }
 
   RegWeight getWeight(const Cfg *Func) const;
 
@@ -554,7 +665,7 @@ public:
   bool mustNotHaveReg() const {
     return RegRequirement == RR_MustNotHaveRegister;
   }
-  void setRematerializable(int32_t NewRegNum, int32_t NewOffset) {
+  void setRematerializable(RegNumT NewRegNum, int32_t NewOffset) {
     IsRematerializable = true;
     setRegNum(NewRegNum);
     setStackOffset(NewOffset);
@@ -593,14 +704,14 @@ public:
   /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
   /// VarsReal.  If NewRegNum!=NoRegister, then that register assignment is made
   /// instead of copying the existing assignment.
-  const Variable *asType(Type Ty, int32_t NewRegNum) const;
+  const Variable *asType(Type Ty, RegNumT NewRegNum) const;
 
   void emit(const Cfg *Func) const override;
   using Operand::dump;
   void dump(const Cfg *Func, Ostream &Str) const override;
 
   /// Return reg num of base register, if different from stack/frame register.
-  virtual int32_t getBaseRegNum() const { return NoRegister; }
+  virtual RegNumT getBaseRegNum() const { return RegNumT::NoRegister; }
 
   static bool classof(const Operand *Operand) {
     OperandKind Kind = Operand->getKind();
@@ -632,9 +743,9 @@ protected:
   RegClass RegisterClass;
   /// RegNum is the allocated register, or NoRegister if it isn't
   /// register-allocated.
-  int32_t RegNum = NoRegister;
+  RegNumT RegNum = RegNumT::NoRegister;
   /// RegNumTmp is the tentative assignment during register allocation.
-  int32_t RegNumTmp = NoRegister;
+  RegNumT RegNumTmp = RegNumT::NoRegister;
   /// StackOffset is the canonical location on stack (only if
   /// RegNum==NoRegister || IsArgument).
   int32_t StackOffset = 0;
index ced9af5..f59cb3c 100644 (file)
@@ -70,7 +70,8 @@ void dumpLiveRange(const Variable *Var, const Cfg *Func) {
     return;
   Ostream &Str = Func->getContext()->getStrDump();
   char buf[30];
-  snprintf(buf, llvm::array_lengthof(buf), "%2d", Var->getRegNumTmp());
+  snprintf(buf, llvm::array_lengthof(buf), "%2u",
+           unsigned(Var->getRegNumTmp()));
   Str << "R=" << buf << "  V=";
   Var->dump(Func);
   Str << "  Range=" << Var->getLiveRange();
@@ -79,13 +80,12 @@ void dumpLiveRange(const Variable *Var, const Cfg *Func) {
 int32_t findMinWeightIndex(
     const llvm::SmallBitVector &RegMask,
     const llvm::SmallVector<RegWeight, LinearScan::REGS_SIZE> &Weights) {
-  int32_t MinWeightIndex = RegMask.find_first();
-  assert(MinWeightIndex >= 0);
-  for (int32_t i = RegMask.find_next(MinWeightIndex); i != -1;
-       i = RegMask.find_next(i)) {
-    if (Weights[i] < Weights[MinWeightIndex])
+  int MinWeightIndex = -1;
+  for (RegNumT i : RegNumBVIter(RegMask)) {
+    if (MinWeightIndex < 0 || Weights[i] < Weights[MinWeightIndex])
       MinWeightIndex = i;
   }
+  assert(MinWeightIndex >= 0);
   return MinWeightIndex;
 }
 
@@ -332,7 +332,7 @@ void LinearScan::init(RegAllocKind Kind) {
   SizeT NumRegs = Target->getNumRegisters();
   RegAliases.resize(NumRegs);
   for (SizeT Reg = 0; Reg < NumRegs; ++Reg) {
-    RegAliases[Reg] = &Target->getAliasesForRegister(Reg);
+    RegAliases[Reg] = &Target->getAliasesForRegister(RegNumT::fromInt(Reg));
   }
 
   switch (Kind) {
@@ -414,8 +414,7 @@ void LinearScan::addSpillFill(IterationState &Iter) {
         if (!Var->hasRegTmp())
           continue;
         const llvm::SmallBitVector &Aliases = *RegAliases[Var->getRegNumTmp()];
-        for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-             RegAlias = Aliases.find_next(RegAlias)) {
+        for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
           Iter.RegMask[RegAlias] = false;
         }
       }
@@ -424,9 +423,8 @@ void LinearScan::addSpillFill(IterationState &Iter) {
   assert(SpillPoint != Insts.end());
   assert(FillPoint != Insts.end());
   ++FillPoint;
-  // TODO(stichnot): Randomize instead of find_first().
-  int32_t RegNum = Iter.RegMask.find_first();
-  assert(RegNum != -1);
+  // TODO(stichnot): Randomize instead of *.begin() which maps to find_first().
+  const RegNumT RegNum = *RegNumBVIter(Iter.RegMask).begin();
   Iter.Cur->setRegNumTmp(RegNum);
   Variable *Preg = Target->getPhysicalRegister(RegNum, Iter.Cur->getType());
   // TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc
@@ -461,8 +459,7 @@ void LinearScan::handleActiveRangeExpiredOrInactive(const Variable *Cur) {
       // Decrement Item from RegUses[].
       assert(Item->hasRegTmp());
       const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
-      for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-           RegAlias = Aliases.find_next(RegAlias)) {
+      for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
         --RegUses[RegAlias];
         assert(RegUses[RegAlias] >= 0);
       }
@@ -486,8 +483,7 @@ void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) {
       // Increment Item in RegUses[].
       assert(Item->hasRegTmp());
       const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
-      for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-           RegAlias = Aliases.find_next(RegAlias)) {
+      for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
         assert(RegUses[RegAlias] >= 0);
         ++RegUses[RegAlias];
       }
@@ -506,7 +502,7 @@ void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) {
 // not appear within the current Variable's live range.
 void LinearScan::findRegisterPreference(IterationState &Iter) {
   Iter.Prefer = nullptr;
-  Iter.PreferReg = Variable::NoRegister;
+  Iter.PreferReg = RegNumT::NoRegister;
   Iter.AllowOverlap = false;
 
   if (!FindPreference)
@@ -529,7 +525,7 @@ void LinearScan::findRegisterPreference(IterationState &Iter) {
     // That register must be one in the RegMask set, e.g. don't try to prefer
     // the stack pointer as a result of the stacksave intrinsic.
     const llvm::SmallBitVector &Aliases = *RegAliases[SrcVar->getRegNumTmp()];
-    const int32_t SrcReg = (Iter.RegMask & Aliases).find_first();
+    const int SrcReg = (Iter.RegMask & Aliases).find_first();
     if (SrcReg == -1)
       continue;
 
@@ -540,7 +536,7 @@ void LinearScan::findRegisterPreference(IterationState &Iter) {
     }
     if (Iter.AllowOverlap || Iter.Free[SrcReg]) {
       Iter.Prefer = SrcVar;
-      Iter.PreferReg = SrcReg;
+      Iter.PreferReg = RegNumT::fromInt(SrcReg);
       // Stop looking for a preference after the first valid preference is
       // found.  One might think that we should look at all instruction
       // variables to find the best <Prefer,AllowOverlap> combination, but note
@@ -566,10 +562,8 @@ void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) {
     if (!Item->rangeOverlaps(Iter.Cur))
       continue;
     const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
-    // TODO(stichnot): Do this with bitvector ops, not a loop, for efficiency.
-    for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-         RegAlias = Aliases.find_next(RegAlias)) {
-      // Don't assert(Iter.Free[RegNum]) because in theory (though probably
+    for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
+      // Don't assert(Iter.Free[RegAlias]) because in theory (though probably
       // never in practice) there could be two inactive variables that were
       // marked with AllowOverlap.
       Iter.Free[RegAlias] = false;
@@ -601,8 +595,7 @@ void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) {
       continue;
     const llvm::SmallBitVector &Aliases =
         *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
-    for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-         RegAlias = Aliases.find_next(RegAlias)) {
+    for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
       Iter.Weights[RegAlias].setWeight(RegWeight::Inf);
       Iter.Free[RegAlias] = false;
       Iter.FreeUnfiltered[RegAlias] = false;
@@ -618,14 +611,13 @@ void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) {
 }
 
 void LinearScan::allocatePrecoloredRegister(Variable *Cur) {
-  int32_t RegNum = Cur->getRegNum();
+  const auto RegNum = Cur->getRegNum();
   // RegNumTmp should have already been set above.
   assert(Cur->getRegNumTmp() == RegNum);
   dumpLiveRangeTrace("Precoloring  ", Cur);
   Active.push_back(Cur);
   const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
-  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-       RegAlias = Aliases.find_next(RegAlias)) {
+  for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
     assert(RegUses[RegAlias] >= 0);
     ++RegUses[RegAlias];
   }
@@ -638,8 +630,7 @@ void LinearScan::allocatePreferredRegister(IterationState &Iter) {
   Iter.Cur->setRegNumTmp(Iter.PreferReg);
   dumpLiveRangeTrace("Preferring   ", Iter.Cur);
   const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
-  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-       RegAlias = Aliases.find_next(RegAlias)) {
+  for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
     assert(RegUses[RegAlias] >= 0);
     ++RegUses[RegAlias];
   }
@@ -647,16 +638,15 @@ void LinearScan::allocatePreferredRegister(IterationState &Iter) {
 }
 
 void LinearScan::allocateFreeRegister(IterationState &Iter, bool Filtered) {
-  const int32_t RegNum =
-      Filtered ? Iter.Free.find_first() : Iter.FreeUnfiltered.find_first();
+  const RegNumT RegNum =
+      *RegNumBVIter(Filtered ? Iter.Free : Iter.FreeUnfiltered).begin();
   Iter.Cur->setRegNumTmp(RegNum);
   if (Filtered)
     dumpLiveRangeTrace("Allocating   ", Iter.Cur);
   else
     dumpLiveRangeTrace("Allocating X ", Iter.Cur);
   const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
-  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-       RegAlias = Aliases.find_next(RegAlias)) {
+  for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
     assert(RegUses[RegAlias] >= 0);
     ++RegUses[RegAlias];
   }
@@ -673,8 +663,7 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
     // should we decide to pick any of them, then we would incur that many
     // memory accesses.
     RegWeight W = Item->getWeight(Func);
-    for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-         RegAlias = Aliases.find_next(RegAlias)) {
+    for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
       Iter.Weights[RegAlias].addWeight(W);
     }
   }
@@ -685,8 +674,7 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
     assert(Item->hasRegTmp());
     const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
     RegWeight W = Item->getWeight(Func);
-    for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-         RegAlias = Aliases.find_next(RegAlias)) {
+    for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
       Iter.Weights[RegAlias].addWeight(W);
     }
   }
@@ -742,16 +730,15 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
   for (SizeT I = Active.size(); I > 0; --I) {
     const SizeT Index = I - 1;
     Variable *Item = Active[Index];
-    int32_t RegNum = Item->getRegNumTmp();
+    const auto RegNum = Item->getRegNumTmp();
     if (Aliases[RegNum]) {
       dumpLiveRangeTrace("Evicting A   ", Item);
       const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
-      for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-           RegAlias = Aliases.find_next(RegAlias)) {
+      for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
         --RegUses[RegAlias];
         assert(RegUses[RegAlias] >= 0);
       }
-      Item->setRegNumTmp(Variable::NoRegister);
+      Item->setRegNumTmp(RegNumT::NoRegister);
       moveItem(Active, Index, Handled);
       Evicted.push_back(Item);
     }
@@ -769,15 +756,14 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
     // instructions.
     if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) {
       dumpLiveRangeTrace("Evicting I   ", Item);
-      Item->setRegNumTmp(Variable::NoRegister);
+      Item->setRegNumTmp(RegNumT::NoRegister);
       moveItem(Inactive, Index, Handled);
       Evicted.push_back(Item);
     }
   }
   // Assign the register to Cur.
-  Iter.Cur->setRegNumTmp(MinWeightIndex);
-  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
-       RegAlias = Aliases.find_next(RegAlias)) {
+  Iter.Cur->setRegNumTmp(RegNumT::fromInt(MinWeightIndex));
+  for (RegNumT RegAlias : RegNumBVIter(Aliases)) {
     assert(RegUses[RegAlias] >= 0);
     ++RegUses[RegAlias];
   }
@@ -789,7 +775,7 @@ void LinearScan::assignFinalRegisters(
     const llvm::SmallBitVector &RegMaskFull,
     const llvm::SmallBitVector &PreDefinedRegisters, bool Randomized) {
   const size_t NumRegisters = RegMaskFull.size();
-  llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters);
+  llvm::SmallVector<RegNumT, REGS_SIZE> Permutation(NumRegisters);
   if (Randomized) {
     // Create a random number generator for regalloc randomization. Merge
     // function's sequence and Kind value as the Salt. Because regAlloc() is
@@ -805,8 +791,8 @@ void LinearScan::assignFinalRegisters(
   // Finish up by setting RegNum = RegNumTmp (or a random permutation thereof)
   // for each Variable.
   for (Variable *Item : Handled) {
-    int32_t RegNum = Item->getRegNumTmp();
-    int32_t AssignedRegNum = RegNum;
+    const auto RegNum = Item->getRegNumTmp();
+    auto AssignedRegNum = RegNum;
 
     if (Randomized && Item->hasRegTmp() && !Item->hasReg()) {
       AssignedRegNum = Permutation[RegNum];
@@ -917,7 +903,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
     if (Iter.AllowOverlap) {
       const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
       for (const Variable *Item : Active) {
-        int32_t RegNum = Item->getRegNumTmp();
+        const RegNumT RegNum = Item->getRegNumTmp();
         if (Item != Iter.Prefer && Aliases[RegNum] &&
             overlapsDefs(Func, Iter.Cur, Item)) {
           Iter.AllowOverlap = false;
@@ -940,8 +926,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
     if (Iter.Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) {
       Iter.Free.reset(KillsMask);
       Iter.FreeUnfiltered.reset(KillsMask);
-      for (int i = KillsMask.find_first(); i != -1;
-           i = KillsMask.find_next(i)) {
+      for (RegNumT i : RegNumBVIter(KillsMask)) {
         Iter.Weights[i].setWeight(RegWeight::Inf);
         if (Iter.PreferReg == i)
           Iter.AllowOverlap = false;
@@ -951,12 +936,10 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
     // Print info about physical register availability.
     if (BuildDefs::dump() && Verbose) {
       Ostream &Str = Ctx->getStrDump();
-      for (SizeT i = 0; i < Iter.RegMask.size(); ++i) {
-        if (Iter.RegMaskUnfiltered[i]) {
-          Str << Target->getRegName(i, Iter.Cur->getType())
-              << "(U=" << RegUses[i] << ",F=" << Iter.Free[i]
-              << ",P=" << Iter.PrecoloredUnhandledMask[i] << ") ";
-        }
+      for (RegNumT i : RegNumBVIter(Iter.RegMaskUnfiltered)) {
+        Str << Target->getRegName(i, Iter.Cur->getType()) << "(U=" << RegUses[i]
+            << ",F=" << Iter.Free[i] << ",P=" << Iter.PrecoloredUnhandledMask[i]
+            << ") ";
       }
       Str << "\n";
     }
index 01c1f3c..299d709 100644 (file)
@@ -58,7 +58,7 @@ private:
     IterationState() = default;
     Variable *Cur = nullptr;
     Variable *Prefer = nullptr;
-    int32_t PreferReg = Variable::NoRegister;
+    RegNumT PreferReg = RegNumT::NoRegister;
     bool AllowOverlap = false;
     llvm::SmallBitVector RegMask;
     llvm::SmallBitVector RegMaskUnfiltered;
index 1ce05ab..6e3c562 100644 (file)
@@ -102,9 +102,13 @@ extern struct RegTableType {
 #undef NUM_ALIASES_BITS
 } RegTable[Reg_NUM];
 
-static inline bool isGPRegister(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline void assertValidRegNum(RegNumT RegNum) {
+  (void)RegNum;
+  assert(RegNum != RegNumT::NoRegister);
+}
+
+static inline bool isGPRegister(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].IsGPR;
 }
 
@@ -118,9 +122,8 @@ static constexpr inline SizeT getNumGPRegs() {
       ;
 }
 
-static inline GPRRegister getEncodedGPR(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return GPRRegister(RegTable[RegNum].Encoding);
 }
 
@@ -134,33 +137,28 @@ static constexpr inline SizeT getNumGPRs() {
       ;
 }
 
-static inline bool isGPR(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline bool isGPR(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].IsGPR;
 }
 
-static inline GPRRegister getI64PairFirstGPRNum(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline GPRRegister getI64PairFirstGPRNum(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return GPRRegister(RegTable[RegNum].Encoding);
 }
 
-static inline GPRRegister getI64PairSecondGPRNum(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline GPRRegister getI64PairSecondGPRNum(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return GPRRegister(RegTable[RegNum].Encoding + 1);
 }
 
-static inline bool isI64RegisterPair(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline bool isI64RegisterPair(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].IsI64Pair;
 }
 
-static inline bool isEncodedSReg(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline bool isEncodedSReg(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].IsFP32;
 }
 
@@ -174,15 +172,13 @@ static constexpr inline SizeT getNumSRegs() {
       ;
 }
 
-static inline SRegister getEncodedSReg(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline SRegister getEncodedSReg(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return SRegister(RegTable[RegNum].Encoding);
 }
 
-static inline bool isEncodedDReg(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline bool isEncodedDReg(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].IsFP64;
 }
 
@@ -196,26 +192,23 @@ static constexpr inline SizeT getNumDRegs() {
       ;
 }
 
-static inline DRegister getEncodedDReg(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline DRegister getEncodedDReg(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return DRegister(RegTable[RegNum].Encoding);
 }
 
-static inline bool isEncodedQReg(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline bool isEncodedQReg(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].IsVec128;
 }
 
-static inline QRegister getEncodedQReg(int32_t RegNum) {
+static inline QRegister getEncodedQReg(RegNumT RegNum) {
   assert(isEncodedQReg(RegNum));
   return QRegister(RegTable[RegNum].Encoding);
 }
 
-static inline IceString getRegName(int32_t RegNum) {
-  assert(RegNum >= 0);
-  assert(RegNum < Reg_NUM);
+static inline IceString getRegName(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegTable[RegNum].Name;
 }
 
index 89c4d89..a707284 100644 (file)
@@ -53,12 +53,13 @@ enum GPRRegister {
 // TODO(jvoung): Floating point and vector registers...
 // Need to model overlap and difference in encoding too.
 
-static inline GPRRegister getEncodedGPR(int32_t RegNum) {
-  assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
+static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
+  assert(int(Reg_GPR_First) <= int(RegNum));
+  assert(unsigned(RegNum) <= Reg_GPR_Last);
   return GPRRegister(RegNum - Reg_GPR_First);
 }
 
-const char *getRegName(int32_t RegNum);
+const char *getRegName(RegNumT RegNum);
 
 } // end of namespace RegMIPS32
 
index 5d71aa7..bb614e0 100644 (file)
@@ -80,10 +80,10 @@ public:
         Encoded_Not_X87STReg = -1
   };
 
-  static inline X87STRegister getEncodedSTReg(int32_t RegNum) {
-    assert(Encoded_X87ST_First <= RegNum);
-    assert(RegNum <= Encoded_X87ST_Last);
-    return X87STRegister(RegNum);
+  static inline X87STRegister getEncodedSTReg(uint32_t X87RegNum) {
+    assert(int(Encoded_X87ST_First) <= int(X87RegNum));
+    assert(X87RegNum <= Encoded_X87ST_Last);
+    return X87STRegister(X87RegNum);
   }
 };
 
index 75886d6..882b4ea 100644 (file)
@@ -119,11 +119,11 @@ Variable *LoweringContext::availabilityGet(Operand *Src) const {
 namespace {
 
 void printRegisterSet(Ostream &Str, const llvm::SmallBitVector &Bitset,
-                      std::function<IceString(int32_t)> getRegName,
+                      std::function<IceString(RegNumT)> getRegName,
                       const IceString &LineIndentString) {
   constexpr size_t RegistersPerLine = 16;
   size_t Count = 0;
-  for (int i = Bitset.find_first(); i != -1; i = Bitset.find_next(i)) {
+  for (RegNumT RegNum : RegNumBVIter(Bitset)) {
     if (Count == 0) {
       Str << LineIndentString;
     } else {
@@ -132,7 +132,7 @@ void printRegisterSet(Ostream &Str, const llvm::SmallBitVector &Bitset,
     if (Count > 0 && Count % RegistersPerLine == 0)
       Str << "\n" << LineIndentString;
     ++Count;
-    Str << getRegName(i);
+    Str << getRegName(RegNum);
   }
   if (Count)
     Str << "\n";
@@ -159,16 +159,18 @@ void splitToClassAndName(const IceString &RegName, IceString *SplitRegClass,
 void TargetLowering::filterTypeToRegisterSet(
     GlobalContext *Ctx, int32_t NumRegs,
     llvm::SmallBitVector TypeToRegisterSet[], size_t TypeToRegisterSetSize,
-    std::function<IceString(int32_t)> getRegName,
+    std::function<IceString(RegNumT)> getRegName,
     std::function<IceString(RegClass)> getRegClassName) {
   std::vector<llvm::SmallBitVector> UseSet(TypeToRegisterSetSize,
                                            llvm::SmallBitVector(NumRegs));
   std::vector<llvm::SmallBitVector> ExcludeSet(TypeToRegisterSetSize,
                                                llvm::SmallBitVector(NumRegs));
 
-  std::unordered_map<IceString, int32_t> RegNameToIndex;
-  for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex)
-    RegNameToIndex[getRegName(RegIndex)] = RegIndex;
+  std::unordered_map<IceString, RegNumT> RegNameToIndex;
+  for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex) {
+    const auto RegNum = RegNumT::fromInt(RegIndex);
+    RegNameToIndex[getRegName(RegNum)] = RegNum;
+  }
 
   ClFlags::StringVector BadRegNames;
 
index 55597ca..a6b6c13 100644 (file)
@@ -233,16 +233,16 @@ public:
   /// generally used to get very direct access to the register such as in the
   /// prolog or epilog or for marking scratch registers as killed by a call. If
   /// a Type is not provided, a target-specific default type is used.
-  virtual Variable *getPhysicalRegister(SizeT RegNum,
+  virtual Variable *getPhysicalRegister(RegNumT RegNum,
                                         Type Ty = IceType_void) = 0;
   /// Returns a printable name for the register.
-  virtual IceString getRegName(SizeT RegNum, Type Ty) const = 0;
+  virtual IceString getRegName(RegNumT RegNum, Type Ty) const = 0;
 
   virtual bool hasFramePointer() const { return false; }
   virtual void setHasFramePointer() = 0;
-  virtual SizeT getStackReg() const = 0;
-  virtual SizeT getFrameReg() const = 0;
-  virtual SizeT getFrameOrStackReg() const = 0;
+  virtual RegNumT getStackReg() const = 0;
+  virtual RegNumT getFrameReg() const = 0;
+  virtual RegNumT getFrameOrStackReg() const = 0;
   virtual size_t typeWidthInBytesOnStack(Type Ty) const = 0;
   virtual uint32_t getStackAlignment() const = 0;
   virtual void reserveFixedAllocaArea(size_t Size, size_t Align) = 0;
@@ -284,12 +284,12 @@ public:
   /// command line.
   virtual const llvm::SmallBitVector &
   getAllRegistersForVariable(const Variable *Var) const = 0;
-  virtual const llvm::SmallBitVector &getAliasesForRegister(SizeT) const = 0;
+  virtual const llvm::SmallBitVector &getAliasesForRegister(RegNumT) const = 0;
 
   void regAlloc(RegAllocKind Kind);
 
   virtual void
-  makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+  makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
                                 const llvm::SmallBitVector &ExcludeRegisters,
                                 uint64_t Salt) const = 0;
 
@@ -363,7 +363,7 @@ protected:
   filterTypeToRegisterSet(GlobalContext *Ctx, int32_t NumRegs,
                           llvm::SmallBitVector TypeToRegisterSet[],
                           size_t TypeToRegisterSetSize,
-                          std::function<IceString(int32_t)> getRegName,
+                          std::function<IceString(RegNumT)> getRegName,
                           std::function<IceString(RegClass)> getRegClassName);
   virtual void lowerAlloca(const InstAlloca *Instr) = 0;
   virtual void lowerArithmetic(const InstArithmetic *Instr) = 0;
index 1dde797..2da5542 100644 (file)
@@ -233,7 +233,7 @@ constexpr SizeT NumGPRArgs =
     REGARM32_GPR_TABLE
 #undef X
     ;
-std::array<uint32_t, NumGPRArgs> GPRArgInitializer;
+std::array<RegNumT, NumGPRArgs> GPRArgInitializer;
 
 constexpr SizeT NumI64Args =
 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
@@ -242,7 +242,7 @@ constexpr SizeT NumI64Args =
     REGARM32_I64PAIR_TABLE
 #undef X
     ;
-std::array<uint32_t, NumI64Args> I64ArgInitializer;
+std::array<RegNumT, NumI64Args> I64ArgInitializer;
 
 constexpr SizeT NumFP32Args =
 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
@@ -251,7 +251,7 @@ constexpr SizeT NumFP32Args =
     REGARM32_FP32_TABLE
 #undef X
     ;
-std::array<uint32_t, NumFP32Args> FP32ArgInitializer;
+std::array<RegNumT, NumFP32Args> FP32ArgInitializer;
 
 constexpr SizeT NumFP64Args =
 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
@@ -260,7 +260,7 @@ constexpr SizeT NumFP64Args =
     REGARM32_FP64_TABLE
 #undef X
     ;
-std::array<uint32_t, NumFP64Args> FP64ArgInitializer;
+std::array<RegNumT, NumFP64Args> FP64ArgInitializer;
 
 constexpr SizeT NumVec128Args =
 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
@@ -269,7 +269,7 @@ constexpr SizeT NumVec128Args =
     REGARM32_VEC128_TABLE
 #undef X
     ;
-std::array<uint32_t, NumVec128Args> Vec128ArgInitializer;
+std::array<RegNumT, NumVec128Args> Vec128ArgInitializer;
 
 IceString getRegClassName(RegClass C) {
   auto ClassNum = static_cast<RegARM32::RegClassARM32>(C);
@@ -289,7 +289,7 @@ TargetARM32::TargetARM32(Cfg *Func)
       CPUFeatures(Func->getContext()->getFlags()) {}
 
 void TargetARM32::staticInit(GlobalContext *Ctx) {
-
+  RegNumT::setLimit(RegARM32::Reg_NUM);
   // Limit this size (or do all bitsets need to be the same width)???
   llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM);
   llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM);
@@ -318,16 +318,17 @@ void TargetARM32::staticInit(GlobalContext *Ctx) {
     if (Entry.CCArg <= 0) {
       continue;
     }
+    const auto RegNum = RegNumT::fromInt(i);
     if (Entry.IsGPR) {
-      GPRArgInitializer[Entry.CCArg - 1] = i;
+      GPRArgInitializer[Entry.CCArg - 1] = RegNum;
     } else if (Entry.IsI64Pair) {
-      I64ArgInitializer[Entry.CCArg - 1] = i;
+      I64ArgInitializer[Entry.CCArg - 1] = RegNum;
     } else if (Entry.IsFP32) {
-      FP32ArgInitializer[Entry.CCArg - 1] = i;
+      FP32ArgInitializer[Entry.CCArg - 1] = RegNum;
     } else if (Entry.IsFP64) {
-      FP64ArgInitializer[Entry.CCArg - 1] = i;
+      FP64ArgInitializer[Entry.CCArg - 1] = RegNum;
     } else if (Entry.IsVec128) {
-      Vec128ArgInitializer[Entry.CCArg - 1] = i;
+      Vec128ArgInitializer[Entry.CCArg - 1] = RegNum;
     }
   }
   TypeToRegisterSet[IceType_void] = InvalidRegisters;
@@ -352,7 +353,7 @@ void TargetARM32::staticInit(GlobalContext *Ctx) {
 
   filterTypeToRegisterSet(
       Ctx, RegARM32::Reg_NUM, TypeToRegisterSet,
-      llvm::array_lengthof(TypeToRegisterSet), [](int32_t RegNum) -> IceString {
+      llvm::array_lengthof(TypeToRegisterSet), [](RegNumT RegNum) -> IceString {
         // This function simply removes ", " from the register name.
         IceString Name = RegARM32::getRegName(RegNum);
         constexpr const char RegSeparator[] = ", ";
@@ -378,7 +379,8 @@ void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) {
     if (!Var64->hasReg()) {
       continue;
     }
-    SizeT FirstReg = RegARM32::getI64PairFirstGPRNum(Var->getRegNum());
+    const auto FirstReg =
+        RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Var->getRegNum()));
     // This assumes little endian.
     Variable *Lo = Var64->getLo();
     Variable *Hi = Var64->getHi();
@@ -388,7 +390,7 @@ void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) {
     }
     Lo->setRegNum(FirstReg);
     Lo->setMustHaveReg();
-    Hi->setRegNum(FirstReg + 1);
+    Hi->setRegNum(RegNumT::fixme(FirstReg + 1));
     Hi->setMustHaveReg();
   }
 }
@@ -396,7 +398,7 @@ void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) {
 
 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) {
   TargetARM32::CallingConv CC;
-  int32_t DummyReg;
+  RegNumT DummyReg;
   size_t OutArgsSizeBytes = 0;
   for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) {
     Operand *Arg = legalizeUndef(Call->getArg(i));
@@ -920,13 +922,12 @@ bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) {
   return false;
 }
 
-IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const {
-  assert(RegNum < RegARM32::Reg_NUM);
+IceString TargetARM32::getRegName(RegNumT RegNum, Type Ty) const {
   (void)Ty;
   return RegARM32::getRegName(RegNum);
 }
 
-Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) {
+Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) {
   static const Type DefaultType[] = {
 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
@@ -937,14 +938,13 @@ Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) {
 #undef X
   };
 
-  assert(RegNum < RegARM32::Reg_NUM);
   if (Ty == IceType_void) {
-    assert(RegNum < llvm::array_lengthof(DefaultType));
+    assert(unsigned(RegNum) < llvm::array_lengthof(DefaultType));
     Ty = DefaultType[RegNum];
   }
   if (PhysicalRegisters[Ty].empty())
     PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM);
-  assert(RegNum < PhysicalRegisters[Ty].size());
+  assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
   Variable *Reg = PhysicalRegisters[Ty][RegNum];
   if (Reg == nullptr) {
     Reg = Func->makeVariable(Ty);
@@ -981,8 +981,8 @@ void TargetARM32::emitVariable(const Variable *Var) const {
   }
   assert(!Var->isRematerializable());
   int32_t Offset = Var->getStackOffset();
-  int32_t BaseRegNum = Var->getBaseRegNum();
-  if (BaseRegNum == Variable::NoRegister) {
+  auto BaseRegNum = Var->getBaseRegNum();
+  if (BaseRegNum == RegNumT::NoRegister) {
     BaseRegNum = getFrameOrStackReg();
   }
   const Type VarTy = Var->getType();
@@ -1002,8 +1002,8 @@ TargetARM32::CallingConv::CallingConv()
       FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()),
       Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {}
 
-bool TargetARM32::CallingConv::argInGPR(Type Ty, int32_t *Reg) {
-  CfgVector<SizeT> *Source;
+bool TargetARM32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
+  CfgVector<RegNumT> *Source;
 
   switch (Ty) {
   default: {
@@ -1037,15 +1037,15 @@ bool TargetARM32::CallingConv::argInGPR(Type Ty, int32_t *Reg) {
 // we remove all of its aliases from the pool of available GPRs. This has the
 // effect of computing the "closure" on the GPR registers.
 void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases(
-    CfgVector<SizeT> *Regs) {
+    CfgVector<RegNumT> *Regs) {
   while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
     GPRegsUsed |= RegisterAliases[Regs->back()];
     Regs->pop_back();
   }
 }
 
-bool TargetARM32::CallingConv::argInVFP(Type Ty, int32_t *Reg) {
-  CfgVector<SizeT> *Source;
+bool TargetARM32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) {
+  CfgVector<RegNumT> *Source;
 
   switch (Ty) {
   default: {
@@ -1075,7 +1075,7 @@ bool TargetARM32::CallingConv::argInVFP(Type Ty, int32_t *Reg) {
 // Arguments in VFP registers are not packed, so we don't mark the popped
 // registers' aliases as unavailable.
 void TargetARM32::CallingConv::discardUnavailableVFPRegs(
-    CfgVector<SizeT> *Regs) {
+    CfgVector<RegNumT> *Regs) {
   while (!Regs->empty() && VFPRegsUsed[Regs->back()]) {
     Regs->pop_back();
   }
@@ -1094,7 +1094,7 @@ void TargetARM32::lowerArguments() {
   for (SizeT I = 0, E = Args.size(); I < E; ++I) {
     Variable *Arg = Args[I];
     Type Ty = Arg->getType();
-    int RegNum;
+    RegNumT RegNum;
     if (isScalarIntegerType(Ty)) {
       if (!CC.argInGPR(Ty, &RegNum)) {
         continue;
@@ -1118,9 +1118,9 @@ void TargetARM32::lowerArguments() {
       auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg);
       RegisterArg64->initHiLo(Func);
       RegisterArg64->getLo()->setRegNum(
-          RegARM32::getI64PairFirstGPRNum(RegNum));
+          RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(RegNum)));
       RegisterArg64->getHi()->setRegNum(
-          RegARM32::getI64PairSecondGPRNum(RegNum));
+          RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(RegNum)));
     } break;
     }
     Context.insert<InstAssign>(Arg, RegisterArg);
@@ -1305,7 +1305,7 @@ void TargetARM32::addProlog(CfgNode *Node) {
         continue;
       }
       ++NumCallee;
-      Variable *PhysicalRegister = getPhysicalRegister(Reg);
+      Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg));
       PreservedRegsSizeBytes +=
           typeWidthInBytesOnStack(PhysicalRegister->getType());
       PreservedRegsInClass->push_back(PhysicalRegister);
@@ -1380,7 +1380,7 @@ void TargetARM32::addProlog(CfgNode *Node) {
   size_t InArgsSizeBytes = 0;
   TargetARM32::CallingConv CC;
   for (Variable *Arg : Args) {
-    int32_t DummyReg;
+    RegNumT DummyReg;
     const Type Ty = Arg->getType();
 
     // Skip arguments passed in registers.
@@ -1499,7 +1499,7 @@ bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const {
 }
 
 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister(
-    Variable *Base, int32_t Offset, int32_t ScratchRegNum) {
+    Variable *Base, int32_t Offset, RegNumT ScratchRegNum) {
   // Legalize will likely need a movw/movt combination, but if the top bits are
   // all 0 from negating the offset and subtracting, we could use that instead.
   const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0;
@@ -1518,7 +1518,7 @@ Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister(
 
   if (ScratchRegNum == Target->getReservedTmpReg()) {
     const bool BaseIsStackOrFramePtr =
-        Base->getRegNum() == static_cast<int32_t>(Target->getFrameOrStackReg());
+        Base->getRegNum() == Target->getFrameOrStackReg();
     // There is currently no code path that would trigger this assertion, so we
     // leave this assertion here in case it is ever violated. This is not a
     // fatal error (thus the use of assert() and not llvm::report_fatal_error)
@@ -1625,10 +1625,9 @@ void TargetARM32::PostLoweringLegalizer::legalizeMov(InstARM32Mov *MovInstr) {
 
       // ExtraOffset is only needed for frame-pointer based frames as we have
       // to account for spill storage.
-      const int32_t ExtraOffset =
-          (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg())
-              ? Target->getFrameFixedAllocaOffset()
-              : 0;
+      const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg())
+                                      ? Target->getFrameFixedAllocaOffset()
+                                      : 0;
 
       const int32_t Offset = Var->getStackOffset() + ExtraOffset;
       Variable *Base = Target->getPhysicalRegister(Var->getRegNum());
@@ -1696,10 +1695,9 @@ TargetARM32::PostLoweringLegalizer::legalizeMemOperand(OperandARM32Mem *Mem,
   Variable *Base = Mem->getBase();
   int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue();
   if (Base->isRematerializable()) {
-    const int32_t ExtraOffset =
-        (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg())
-            ? Target->getFrameFixedAllocaOffset()
-            : 0;
+    const int32_t ExtraOffset = (Base->getRegNum() == Target->getFrameReg())
+                                    ? Target->getFrameFixedAllocaOffset()
+                                    : 0;
     Offset += Base->getStackOffset() + ExtraOffset;
     Base = Target->getPhysicalRegister(Base->getRegNum());
     assert(!Base->isRematerializable());
@@ -1919,7 +1917,7 @@ llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include,
                                                  RegSetMask Exclude) const {
   llvm::SmallBitVector Registers(RegARM32::Reg_NUM);
 
-  for (int32_t i = 0; i < RegARM32::Reg_NUM; ++i) {
+  for (uint32_t i = 0; i < RegARM32::Reg_NUM; ++i) {
     const auto &Entry = RegARM32::RegTable[i];
     if (Entry.Scratch && (Include & RegSet_CallerSave))
       Registers[i] = true;
@@ -3383,8 +3381,8 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
   // Assign arguments to registers and stack. Also reserve stack.
   TargetARM32::CallingConv CC;
   // Pair of Arg Operand -> GPR number assignments.
-  llvm::SmallVector<std::pair<Operand *, int32_t>, NumGPRArgs> GPRArgs;
-  llvm::SmallVector<std::pair<Operand *, int32_t>, NumFP32Args> FPArgs;
+  llvm::SmallVector<std::pair<Operand *, RegNumT>, NumGPRArgs> GPRArgs;
+  llvm::SmallVector<std::pair<Operand *, RegNumT>, NumFP32Args> FPArgs;
   // Pair of Arg Operand -> stack offset.
   llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs;
   size_t ParameterAreaSizeBytes = 0;
@@ -3395,7 +3393,7 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
     Operand *Arg = legalizeUndef(Instr->getArg(i));
     const Type Ty = Arg->getType();
     bool InReg = false;
-    int32_t Reg;
+    RegNumT Reg;
     if (isScalarIntegerType(Ty)) {
       InReg = CC.argInGPR(Ty, &Reg);
     } else {
@@ -3413,10 +3411,10 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
     if (Ty == IceType_i64) {
       Operand *Lo = loOperand(Arg);
       Operand *Hi = hiOperand(Arg);
-      GPRArgs.push_back(
-          std::make_pair(Lo, RegARM32::getI64PairFirstGPRNum(Reg)));
-      GPRArgs.push_back(
-          std::make_pair(Hi, RegARM32::getI64PairSecondGPRNum(Reg)));
+      GPRArgs.push_back(std::make_pair(
+          Lo, RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Reg))));
+      GPRArgs.push_back(std::make_pair(
+          Hi, RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(Reg))));
     } else if (isScalarIntegerType(Ty)) {
       GPRArgs.push_back(std::make_pair(Arg, Reg));
     } else {
@@ -5518,7 +5516,7 @@ void TargetARM32::prelowerPhis() {
   PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func);
 }
 
-Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
+Variable *TargetARM32::makeVectorOfZeros(Type Ty, RegNumT RegNum) {
   Variable *Reg = makeReg(Ty, RegNum);
   Context.insert<InstFakeDef>(Reg);
   assert(isVectorType(Ty));
@@ -5528,7 +5526,7 @@ Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
 
 // Helper for legalize() to emit the right code to lower an operand to a
 // register of the appropriate type.
-Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) {
+Variable *TargetARM32::copyToReg(Operand *Src, RegNumT RegNum) {
   Type Ty = Src->getType();
   Variable *Reg = makeReg(Ty, RegNum);
   if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
@@ -5541,7 +5539,7 @@ Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) {
 
 // TODO(jpp): remove unneeded else clauses in legalize.
 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
-                               int32_t RegNum) {
+                               RegNumT RegNum) {
   Type Ty = From->getType();
   // Assert that a physical register is allowed. To date, all calls to
   // legalize() allow a physical register. Legal_Flex converts registers to the
@@ -5549,7 +5547,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
   assert(Allowed & Legal_Reg);
 
   // Copied ipsis literis from TargetX86Base<Machine>.
-  if (RegNum == Variable::NoRegister) {
+  if (RegNum == RegNumT::NoRegister) {
     if (Variable *Subst = getContext().availabilityGet(From)) {
       // At this point we know there is a potential substitution available.
       if (!Subst->isRematerializable() && Subst->mustHaveReg() &&
@@ -5733,7 +5731,7 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
     //   register, or
     //   RegNum is required and Var->getRegNum() doesn't match.
     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
-        (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+        (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
       From = copyToReg(From, RegNum);
     }
     return From;
@@ -5744,12 +5742,12 @@ Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
 }
 
 /// Provide a trivial wrapper to legalize() for this common usage.
-Variable *TargetARM32::legalizeToReg(Operand *From, int32_t RegNum) {
+Variable *TargetARM32::legalizeToReg(Operand *From, RegNumT RegNum) {
   return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
 }
 
 /// Legalize undef values to concrete values.
-Operand *TargetARM32::legalizeUndef(Operand *From, int32_t RegNum) {
+Operand *TargetARM32::legalizeUndef(Operand *From, RegNumT RegNum) {
   Type Ty = From->getType();
   if (llvm::isa<ConstantUndef>(From)) {
     // Lower undefs to zero. Another option is to lower undefs to an
@@ -5797,12 +5795,12 @@ Variable64On32 *TargetARM32::makeI64RegPair() {
   return Reg;
 }
 
-Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) {
+Variable *TargetARM32::makeReg(Type Type, RegNumT RegNum) {
   // There aren't any 64-bit integer registers for ARM32.
   assert(Type != IceType_i64);
-  assert(AllowTemporaryWithNoReg || RegNum != Variable::NoRegister);
+  assert(AllowTemporaryWithNoReg || RegNum != RegNumT::NoRegister);
   Variable *Reg = Func->makeVariable(Type);
-  if (RegNum == Variable::NoRegister)
+  if (RegNum == RegNumT::NoRegister)
     Reg->setMustHaveReg();
   else
     Reg->setRegNum(RegNum);
@@ -5810,7 +5808,7 @@ Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) {
 }
 
 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align,
-                                    int32_t TmpRegNum) {
+                                    RegNumT TmpRegNum) {
   assert(llvm::isPowerOf2_32(Align));
   uint32_t RotateAmt;
   uint32_t Immed_8;
@@ -5837,7 +5835,7 @@ void TargetARM32::postLower() {
 }
 
 void TargetARM32::makeRandomRegisterPermutation(
-    llvm::SmallVectorImpl<int32_t> &Permutation,
+    llvm::SmallVectorImpl<RegNumT> &Permutation,
     const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
   (void)Permutation;
   (void)ExcludeRegisters;
index 97a944c..02c13fc 100644 (file)
@@ -78,8 +78,9 @@ public:
   bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
 
   SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
-  Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
-  IceString getRegName(SizeT RegNum, Type Ty) const override;
+  Variable *getPhysicalRegister(RegNumT RegNum,
+                                Type Ty = IceType_void) override;
+  IceString getRegName(RegNumT RegNum, Type Ty) const override;
   llvm::SmallBitVector getRegisterSet(RegSetMask Include,
                                       RegSetMask Exclude) const override;
   const llvm::SmallBitVector &
@@ -99,17 +100,18 @@ public:
     assert((RegARM32::RegClassARM32)RC < RegARM32::RCARM32_NUM);
     return TypeToRegisterSetUnfiltered[RC];
   }
-  const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+  const llvm::SmallBitVector &
+  getAliasesForRegister(RegNumT Reg) const override {
     return RegisterAliases[Reg];
   }
   bool hasFramePointer() const override { return UsesFramePointer; }
   void setHasFramePointer() override { UsesFramePointer = true; }
-  SizeT getStackReg() const override { return RegARM32::Reg_sp; }
-  SizeT getFrameReg() const override { return RegARM32::Reg_fp; }
-  SizeT getFrameOrStackReg() const override {
+  RegNumT getStackReg() const override { return RegARM32::Reg_sp; }
+  RegNumT getFrameReg() const override { return RegARM32::Reg_fp; }
+  RegNumT getFrameOrStackReg() const override {
     return UsesFramePointer ? getFrameReg() : getStackReg();
   }
-  int32_t getReservedTmpReg() const { return RegARM32::Reg_ip; }
+  RegNumT getReservedTmpReg() const { return RegARM32::Reg_ip; }
 
   size_t typeWidthInBytesOnStack(Type Ty) const override {
     // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
@@ -169,10 +171,10 @@ public:
   };
 
   using LegalMask = uint32_t;
-  Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
+  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
-                    int32_t RegNum = Variable::NoRegister);
-  Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
+                    RegNumT RegNum = RegNumT::NoRegister);
+  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
 
   OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
     assert(ShAmtImm < 32);
@@ -265,17 +267,17 @@ protected:
   OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
 
   Variable64On32 *makeI64RegPair();
-  Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
+  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
   static Type stackSlotType();
-  Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
+  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
   void alignRegisterPow2(Variable *Reg, uint32_t Align,
-                         int32_t TmpRegNum = Variable::NoRegister);
+                         RegNumT TmpRegNum = RegNumT::NoRegister);
 
   /// Returns a vector in a register with the given constant entries.
-  Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
+  Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
 
   void
-  makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+  makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
                                 const llvm::SmallBitVector &ExcludeRegisters,
                                 uint64_t Salt) const override;
 
@@ -1014,7 +1016,7 @@ protected:
   private:
     /// Creates a new Base register centered around [Base, +/- Offset].
     Variable *newBaseRegister(Variable *Base, int32_t Offset,
-                              int32_t ScratchRegNum);
+                              RegNumT ScratchRegNum);
 
     /// Creates a new, legal OperandARM32Mem for accessing Base + Offset.
     /// The returned mem operand is a legal operand for accessing memory that is
@@ -1081,23 +1083,23 @@ protected:
     /// type, and false otherwise. If it returns true, Reg is set to the
     /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
     /// be an I64 register pair.
-    bool argInGPR(Type Ty, int32_t *Reg);
+    bool argInGPR(Type Ty, RegNumT *Reg);
 
     /// argInVFP is to floating-point/vector types what argInGPR is for integer
     /// types.
-    bool argInVFP(Type Ty, int32_t *Reg);
+    bool argInVFP(Type Ty, RegNumT *Reg);
 
   private:
-    void discardUnavailableGPRsAndTheirAliases(CfgVector<SizeT> *Regs);
+    void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
     llvm::SmallBitVector GPRegsUsed;
-    CfgVector<SizeT> GPRArgs;
-    CfgVector<SizeT> I64Args;
+    CfgVector<RegNumT> GPRArgs;
+    CfgVector<RegNumT> I64Args;
 
-    void discardUnavailableVFPRegs(CfgVector<SizeT> *Regs);
+    void discardUnavailableVFPRegs(CfgVector<RegNumT> *Regs);
     llvm::SmallBitVector VFPRegsUsed;
-    CfgVector<SizeT> FP32Args;
-    CfgVector<SizeT> FP64Args;
-    CfgVector<SizeT> Vec128Args;
+    CfgVector<RegNumT> FP32Args;
+    CfgVector<RegNumT> FP64Args;
+    CfgVector<RegNumT> Vec128Args;
   };
 
 private:
index 40d510d..e34dd5d 100644 (file)
@@ -77,6 +77,7 @@ TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {}
 
 void TargetMIPS32::staticInit(GlobalContext *Ctx) {
   (void)Ctx;
+  RegNumT::setLimit(RegMIPS32::Reg_NUM);
   llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM);
   llvm::SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM);
   llvm::SmallBitVector Float32Registers(RegMIPS32::Reg_NUM);
@@ -290,22 +291,22 @@ const char *RegNames[RegMIPS32::Reg_NUM] = {
 
 } // end of anonymous namespace
 
-const char *RegMIPS32::getRegName(int32_t RegNum) {
-  assert(RegNum < RegMIPS32::Reg_NUM);
+const char *RegMIPS32::getRegName(RegNumT RegNum) {
+  RegNum.assertIsValid();
   return RegNames[RegNum];
 }
 
-IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const {
+IceString TargetMIPS32::getRegName(RegNumT RegNum, Type Ty) const {
   (void)Ty;
   return RegMIPS32::getRegName(RegNum);
 }
 
-Variable *TargetMIPS32::getPhysicalRegister(SizeT RegNum, Type Ty) {
+Variable *TargetMIPS32::getPhysicalRegister(RegNumT RegNum, Type Ty) {
   if (Ty == IceType_void)
     Ty = IceType_i32;
   if (PhysicalRegisters[Ty].empty())
     PhysicalRegisters[Ty].resize(RegMIPS32::Reg_NUM);
-  assert(RegNum < PhysicalRegisters[Ty].size());
+  RegNum.assertIsValid();
   Variable *Reg = PhysicalRegisters[Ty][RegNum];
   if (Reg == nullptr) {
     Reg = Func->makeVariable(Ty);
@@ -328,12 +329,12 @@ void TargetMIPS32::emitJumpTable(const Cfg *Func,
 }
 
 /// Provide a trivial wrapper to legalize() for this common usage.
-Variable *TargetMIPS32::legalizeToReg(Operand *From, int32_t RegNum) {
+Variable *TargetMIPS32::legalizeToReg(Operand *From, RegNumT RegNum) {
   return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
 }
 
 /// Legalize undef values to concrete values.
-Operand *TargetMIPS32::legalizeUndef(Operand *From, int32_t RegNum) {
+Operand *TargetMIPS32::legalizeUndef(Operand *From, RegNumT RegNum) {
   (void)RegNum;
   Type Ty = From->getType();
   if (llvm::isa<ConstantUndef>(From)) {
@@ -355,11 +356,11 @@ Operand *TargetMIPS32::legalizeUndef(Operand *From, int32_t RegNum) {
   return From;
 }
 
-Variable *TargetMIPS32::makeReg(Type Type, int32_t RegNum) {
+Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) {
   // There aren't any 64-bit integer registers for Mips32.
   assert(Type != IceType_i64);
   Variable *Reg = Func->makeVariable(Type);
-  if (RegNum == Variable::NoRegister)
+  if (RegNum == RegNumT::NoRegister)
     Reg->setMustHaveReg();
   else
     Reg->setRegNum(RegNum);
@@ -410,20 +411,20 @@ void TargetMIPS32::lowerArguments() {
     if (Ty == IceType_i64) {
       if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
         continue;
-      int32_t RegLo = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
-      int32_t RegHi = RegLo + 1;
+      auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed);
+      auto RegHi = RegNumT::fixme(RegLo + 1);
       ++NumGPRRegsUsed;
       // Always start i64 registers at an even register, so this may end
       // up padding away a register.
       if (RegLo % 2 != 0) {
-        ++RegLo;
+        RegLo = RegNumT::fixme(RegLo + 1);
         ++NumGPRRegsUsed;
       }
       // If this leaves us without room to consume another register,
       // leave any previously speculatively consumed registers as consumed.
       if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
         continue;
-      // RegHi = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+      // RegHi = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed);
       ++NumGPRRegsUsed;
       Variable *RegisterArg = Func->makeVariable(Ty);
       auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg);
@@ -441,7 +442,7 @@ void TargetMIPS32::lowerArguments() {
       assert(Ty == IceType_i32);
       if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG)
         continue;
-      int32_t RegNum = RegMIPS32::Reg_A0 + NumGPRRegsUsed;
+      const auto RegNum = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed);
       ++NumGPRRegsUsed;
       Variable *RegisterArg = Func->makeVariable(Ty);
       if (BuildDefs::dump()) {
@@ -1156,7 +1157,7 @@ void TargetMIPS32::postLower() {
 }
 
 void TargetMIPS32::makeRandomRegisterPermutation(
-    llvm::SmallVectorImpl<int32_t> &Permutation,
+    llvm::SmallVectorImpl<RegNumT> &Permutation,
     const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
   (void)Permutation;
   (void)ExcludeRegisters;
@@ -1213,7 +1214,7 @@ void TargetDataMIPS32::lowerJumpTables() {
 
 // Helper for legalize() to emit the right code to lower an operand to a
 // register of the appropriate type.
-Variable *TargetMIPS32::copyToReg(Operand *Src, int32_t RegNum) {
+Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) {
   Type Ty = Src->getType();
   Variable *Reg = makeReg(Ty, RegNum);
   if (isVectorType(Ty) || isFloatingType(Ty)) {
@@ -1227,7 +1228,7 @@ Variable *TargetMIPS32::copyToReg(Operand *Src, int32_t RegNum) {
 }
 
 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
-                                int32_t RegNum) {
+                                RegNumT RegNum) {
   Type Ty = From->getType();
   // Assert that a physical register is allowed.  To date, all calls
   // to legalize() allow a physical register. Legal_Flex converts
@@ -1252,7 +1253,7 @@ Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
     // Also try the inverse and use MVN if possible.
     // Do a movw/movt to a register.
     Variable *Reg;
-    if (RegNum == Variable::NoRegister)
+    if (RegNum == RegNumT::NoRegister)
       Reg = makeReg(Ty, RegNum);
     else
       Reg = getPhysicalRegister(RegNum);
@@ -1280,7 +1281,7 @@ Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
     //   register, or
     //   RegNum is required and Var->getRegNum() doesn't match.
     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
-        (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+        (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
       From = copyToReg(From, RegNum);
     }
     return From;
index a61263e..7608de1 100644 (file)
@@ -47,8 +47,9 @@ public:
   bool doBranchOpt(Inst *Instr, const CfgNode *NextNode) override;
 
   SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
-  Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
-  IceString getRegName(SizeT RegNum, Type Ty) const override;
+  Variable *getPhysicalRegister(RegNumT RegNum,
+                                Type Ty = IceType_void) override;
+  IceString getRegName(RegNumT RegNum, Type Ty) const override;
   llvm::SmallBitVector getRegisterSet(RegSetMask Include,
                                       RegSetMask Exclude) const override;
   const llvm::SmallBitVector &
@@ -63,14 +64,15 @@ public:
     assert(RC < RC_Target);
     return TypeToRegisterSetUnfiltered[RC];
   }
-  const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+  const llvm::SmallBitVector &
+  getAliasesForRegister(RegNumT Reg) const override {
     return RegisterAliases[Reg];
   }
   bool hasFramePointer() const override { return UsesFramePointer; }
   void setHasFramePointer() override { UsesFramePointer = true; }
-  SizeT getStackReg() const override { return RegMIPS32::Reg_SP; }
-  SizeT getFrameReg() const override { return RegMIPS32::Reg_FP; }
-  SizeT getFrameOrStackReg() const override {
+  RegNumT getStackReg() const override { return RegMIPS32::Reg_SP; }
+  RegNumT getFrameReg() const override { return RegMIPS32::Reg_FP; }
+  RegNumT getFrameOrStackReg() const override {
     return UsesFramePointer ? getFrameReg() : getStackReg();
   }
   size_t typeWidthInBytesOnStack(Type Ty) const override {
@@ -218,15 +220,15 @@ public:
   };
   typedef uint32_t LegalMask;
   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
-                    int32_t RegNum = Variable::NoRegister);
+                    RegNumT RegNum = RegNumT::NoRegister);
 
-  Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
+  Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
 
-  Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
+  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
 
-  Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
+  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
   static Type stackSlotType();
-  Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
+  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
 
   void addProlog(CfgNode *Node) override;
   void addEpilog(CfgNode *Node) override;
@@ -238,7 +240,7 @@ public:
   Operand *loOperand(Operand *Operand);
   Operand *hiOperand(Operand *Operand);
 
-  Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
+  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
 
 protected:
   explicit TargetMIPS32(Cfg *Func);
@@ -276,7 +278,7 @@ protected:
   void randomlyInsertNop(float Probability,
                          RandomNumberGenerator &RNG) override;
   void
-  makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+  makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
                                 const llvm::SmallBitVector &ExcludeRegisters,
                                 uint64_t Salt) const override;
 
index 53d50fb..8b5412d 100644 (file)
@@ -68,8 +68,8 @@ struct TargetX8632Traits {
   using Cond = ::Ice::CondX86;
 
   using RegisterSet = ::Ice::RegX8632;
-  static constexpr SizeT StackPtr = RegX8632::Reg_esp;
-  static constexpr SizeT FramePtr = RegX8632::Reg_ebp;
+  static constexpr RegisterSet::AllRegisters StackPtr = RegX8632::Reg_esp;
+  static constexpr RegisterSet::AllRegisters FramePtr = RegX8632::Reg_ebp;
   static constexpr GPRRegister Encoded_Reg_Accumulator =
       RegX8632::Encoded_Reg_eax;
   static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
@@ -276,7 +276,7 @@ struct TargetX8632Traits {
   static const char *TargetName;
   static constexpr Type WordType = IceType_i32;
 
-  static IceString getRegName(int32_t RegNum) {
+  static IceString getRegName(RegNumT RegNum) {
     static const char *const RegNames[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
@@ -285,12 +285,11 @@ struct TargetX8632Traits {
         REGX8632_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     return RegNames[RegNum];
   }
 
-  static GPRRegister getEncodedGPR(int32_t RegNum) {
+  static GPRRegister getEncodedGPR(RegNumT RegNum) {
     static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
@@ -299,13 +298,12 @@ struct TargetX8632Traits {
         REGX8632_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
     return GPRRegs[RegNum];
   }
 
-  static ByteRegister getEncodedByteReg(int32_t RegNum) {
+  static ByteRegister getEncodedByteReg(RegNumT RegNum) {
     static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
@@ -314,13 +312,12 @@ struct TargetX8632Traits {
         REGX8632_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
     return ByteRegs[RegNum];
   }
 
-  static XmmRegister getEncodedXmm(int32_t RegNum) {
+  static XmmRegister getEncodedXmm(RegNumT RegNum) {
     static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
@@ -329,13 +326,12 @@ struct TargetX8632Traits {
         REGX8632_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
     return XmmRegs[RegNum];
   }
 
-  static uint32_t getEncoding(int32_t RegNum) {
+  static uint32_t getEncoding(RegNumT RegNum) {
     static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
@@ -344,13 +340,12 @@ struct TargetX8632Traits {
         REGX8632_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     return Encoding[RegNum];
   }
 
-  static int32_t getBaseReg(int32_t RegNum) {
-    static const int32_t BaseRegs[RegisterSet::Reg_NUM] = {
+  static RegNumT getBaseReg(RegNumT RegNum) {
+    static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
@@ -358,13 +353,12 @@ struct TargetX8632Traits {
         REGX8632_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     return BaseRegs[RegNum];
   }
 
 private:
-  static int32_t getFirstGprForType(Type Ty) {
+  static RegisterSet::AllRegisters getFirstGprForType(Type Ty) {
     switch (Ty) {
     default:
       llvm_unreachable("Invalid type for GPR.");
@@ -380,8 +374,8 @@ private:
 
 public:
   // Return a register in RegNum's alias set that is suitable for Ty.
-  static int32_t getGprForType(Type Ty, int32_t RegNum) {
-    assert(RegNum != Variable::NoRegister);
+  static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
+    assert(RegNum != RegNumT::NoRegister);
 
     if (!isScalarIntegerType(Ty)) {
       return RegNum;
@@ -399,7 +393,7 @@ public:
       return RegNum;
     }
 
-    const int32_t FirstGprForType = getFirstGprForType(Ty);
+    const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty);
 
     switch (RegNum) {
     default:
@@ -412,14 +406,14 @@ public:
       return RegisterSet::val;                                                 \
     assert((is32) || (is16) || (is8) ||                                        \
            getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp);              \
-    constexpr int32_t FirstGprWithRegNumSize =                                 \
+    constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
         (((is32) || RegisterSet::val == RegisterSet::Reg_esp)                  \
              ? RegisterSet::Reg_eax                                            \
              : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)            \
                     ? RegisterSet::Reg_ax                                      \
                     : RegisterSet::Reg_al));                                   \
-    const int32_t NewRegNum =                                                  \
-        RegNum - FirstGprWithRegNumSize + FirstGprForType;                     \
+    const RegNumT NewRegNum =                                                  \
+        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
     assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
            "Error involving " #val);                                           \
     return NewRegNum;                                                          \
@@ -580,7 +574,7 @@ public:
 
   static void
   makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
-                                llvm::SmallVectorImpl<int32_t> &Permutation,
+                                llvm::SmallVectorImpl<RegNumT> &Permutation,
                                 const llvm::SmallBitVector &ExcludeRegisters,
                                 uint64_t Salt) {
     // TODO(stichnot): Declaring Permutation this way loses type/size
@@ -590,7 +584,7 @@ public:
     // class. For x86-32, this would comprise the 8 XMM registers. This is for
     // performance, not correctness.
     static const unsigned MaxEquivalenceClassSize = 8;
-    using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>;
+    using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
     using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
     EquivalenceClassMap EquivalenceClasses;
     SizeT NumShuffled = 0, NumPreserved = 0;
@@ -652,7 +646,7 @@ public:
         Str << "{";
         const RegisterList &List = I.second;
         bool First = true;
-        for (int32_t Register : List) {
+        for (RegNumT Register : List) {
           if (!First)
             Str << " ";
           First = false;
@@ -663,11 +657,11 @@ public:
     }
   }
 
-  static int32_t getRaxOrDie() {
+  static RegNumT getRaxOrDie() {
     llvm::report_fatal_error("no rax in non-64-bit mode.");
   }
 
-  static int32_t getRdxOrDie() {
+  static RegNumT getRdxOrDie() {
     llvm::report_fatal_error("no rdx in non-64-bit mode.");
   }
 
@@ -687,21 +681,21 @@ public:
   /// Whether scalar floating point arguments are passed in XMM registers
   static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false;
   /// Get the register for a given argument slot in the XMM registers.
-  static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
+  static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
     // TODO(sehr): Change to use the CCArg technique used in ARM32.
     static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
                   "Inconsistency between XMM register numbers and ordinals");
     if (ArgNum >= X86_MAX_XMM_ARGS) {
-      return Variable::NoRegister;
+      return RegNumT::NoRegister;
     }
-    return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
+    return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
   }
   /// Get the register for a given argument slot in the GPRs.
-  static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+  static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
     assert(Ty == IceType_i64 || Ty == IceType_i32);
     (void)Ty;
     (void)ArgNum;
-    return Variable::NoRegister;
+    return RegNumT::NoRegister;
   }
 
   /// The number of bits in a byte
index 9b99e81..ecf86b0 100644 (file)
@@ -312,7 +312,7 @@ bool isAssignedToRspOrRbp(const Variable *Var) {
     return false;
   }
 
-  const int32_t RegNum = Var->getRegNum();
+  const auto RegNum = Var->getRegNum();
   if ((RegNum == Traits::RegisterSet::Reg_rsp) ||
       (RegNum == Traits::RegisterSet::Reg_rbp)) {
     return true;
@@ -419,8 +419,8 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
     }
   }
 
-  int32_t RegNum = Variable::NoRegister;
-  int32_t RegNum32 = Variable::NoRegister;
+  auto RegNum = RegNumT::NoRegister;
+  auto RegNum32 = RegNumT::NoRegister;
   if (T != nullptr) {
     if (T->hasReg()) {
       RegNum = Traits::getGprForType(IceType_i64, T->getRegNum());
index 336e3df..18e054a 100644 (file)
@@ -68,8 +68,8 @@ struct TargetX8664Traits {
   using Cond = ::Ice::CondX8664;
 
   using RegisterSet = ::Ice::RegX8664;
-  static constexpr SizeT StackPtr = RegX8664::Reg_rsp;
-  static constexpr SizeT FramePtr = RegX8664::Reg_rbp;
+  static constexpr RegisterSet::AllRegisters StackPtr = RegX8664::Reg_rsp;
+  static constexpr RegisterSet::AllRegisters FramePtr = RegX8664::Reg_rbp;
   static constexpr GPRRegister Encoded_Reg_Accumulator =
       RegX8664::Encoded_Reg_eax;
   static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx;
@@ -301,7 +301,7 @@ struct TargetX8664Traits {
   static const char *TargetName;
   static constexpr Type WordType = IceType_i64;
 
-  static IceString getRegName(int32_t RegNum) {
+  static IceString getRegName(RegNumT RegNum) {
     static const char *const RegNames[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
@@ -310,12 +310,11 @@ struct TargetX8664Traits {
         REGX8664_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     return RegNames[RegNum];
   }
 
-  static GPRRegister getEncodedGPR(int32_t RegNum) {
+  static GPRRegister getEncodedGPR(RegNumT RegNum) {
     static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
@@ -324,13 +323,12 @@ struct TargetX8664Traits {
         REGX8664_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
     return GPRRegs[RegNum];
   }
 
-  static ByteRegister getEncodedByteReg(int32_t RegNum) {
+  static ByteRegister getEncodedByteReg(RegNumT RegNum) {
     static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
@@ -339,13 +337,12 @@ struct TargetX8664Traits {
         REGX8664_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
     return ByteRegs[RegNum];
   }
 
-  static XmmRegister getEncodedXmm(int32_t RegNum) {
+  static XmmRegister getEncodedXmm(RegNumT RegNum) {
     static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
@@ -354,13 +351,12 @@ struct TargetX8664Traits {
         REGX8664_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
     return XmmRegs[RegNum];
   }
 
-  static uint32_t getEncoding(int32_t RegNum) {
+  static uint32_t getEncoding(RegNumT RegNum) {
     static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
@@ -369,27 +365,25 @@ struct TargetX8664Traits {
         REGX8664_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     return Encoding[RegNum];
   }
 
-  static inline int32_t getBaseReg(int32_t RegNum) {
-    static const int32_t BaseRegs[RegisterSet::Reg_NUM] = {
+  static inline RegNumT getBaseReg(RegNumT RegNum) {
+    static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
           sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
           is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  encode,
+  RegisterSet::base,
         REGX8664_TABLE
 #undef X
     };
-    assert(RegNum >= 0);
-    assert(RegNum < RegisterSet::Reg_NUM);
+    RegNum.assertIsValid();
     return BaseRegs[RegNum];
   }
 
 private:
-  static int32_t getFirstGprForType(Type Ty) {
+  static RegNumT getFirstGprForType(Type Ty) {
     switch (Ty) {
     default:
       llvm_unreachable("Invalid type for GPR.");
@@ -406,8 +400,8 @@ private:
   }
 
 public:
-  static int32_t getGprForType(Type Ty, int32_t RegNum) {
-    assert(RegNum != Variable::NoRegister);
+  static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
+    assert(RegNum != RegNumT::NoRegister);
 
     if (!isScalarIntegerType(Ty)) {
       return RegNum;
@@ -425,7 +419,7 @@ public:
     assert(RegNum != RegisterSet::Reg_ch);
     assert(RegNum != RegisterSet::Reg_dh);
 
-    const int32_t FirstGprForType = getFirstGprForType(Ty);
+    const RegNumT FirstGprForType = getFirstGprForType(Ty);
 
     switch (RegNum) {
     default:
@@ -438,7 +432,7 @@ public:
       return RegisterSet::val;                                                 \
     assert((is64) || (is32) || (is16) || (is8) ||                              \
            getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp);              \
-    constexpr int32_t FirstGprWithRegNumSize =                                 \
+    constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
         ((is64) || RegisterSet::val == RegisterSet::Reg_rsp)                   \
             ? RegisterSet::Reg_rax                                             \
             : (((is32) || RegisterSet::val == RegisterSet::Reg_esp)            \
@@ -446,8 +440,8 @@ public:
                    : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)      \
                           ? RegisterSet::Reg_ax                                \
                           : RegisterSet::Reg_al));                             \
-    const int32_t NewRegNum =                                                  \
-        RegNum - FirstGprWithRegNumSize + FirstGprForType;                     \
+    const auto NewRegNum =                                                     \
+        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
     assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
            "Error involving " #val);                                           \
     return NewRegNum;                                                          \
@@ -624,7 +618,7 @@ public:
 
   static void
   makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
-                                llvm::SmallVectorImpl<int32_t> &Permutation,
+                                llvm::SmallVectorImpl<RegNumT> &Permutation,
                                 const llvm::SmallBitVector &ExcludeRegisters,
                                 uint64_t Salt) {
     // TODO(stichnot): Declaring Permutation this way loses type/size
@@ -634,7 +628,7 @@ public:
     // class.  For x86-64, this would comprise the 16 XMM registers. This is
     // for performance, not correctness.
     static const unsigned MaxEquivalenceClassSize = 8;
-    using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>;
+    using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
     using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
     EquivalenceClassMap EquivalenceClasses;
     SizeT NumShuffled = 0, NumPreserved = 0;
@@ -696,7 +690,7 @@ public:
         Str << "{";
         const RegisterList &List = I.second;
         bool First = true;
-        for (int32_t Register : List) {
+        for (RegNumT Register : List) {
           if (!First)
             Str << " ";
           First = false;
@@ -707,9 +701,9 @@ public:
     }
   }
 
-  static int32_t getRaxOrDie() { return RegisterSet::Reg_rax; }
+  static RegNumT getRaxOrDie() { return RegisterSet::Reg_rax; }
 
-  static int32_t getRdxOrDie() { return RegisterSet::Reg_rdx; }
+  static RegNumT getRdxOrDie() { return RegisterSet::Reg_rdx; }
 
   // x86-64 calling convention:
   //
@@ -731,19 +725,19 @@ public:
   /// Whether scalar floating point arguments are passed in XMM registers
   static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true;
   /// Get the register for a given argument slot in the XMM registers.
-  static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
+  static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
     // TODO(sehr): Change to use the CCArg technique used in ARM32.
     static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
                   "Inconsistency between XMM register numbers and ordinals");
     if (ArgNum >= X86_MAX_XMM_ARGS) {
-      return Variable::NoRegister;
+      return RegNumT::NoRegister;
     }
-    return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
+    return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
   }
   /// Get the register for a given argument slot in the GPRs.
-  static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+  static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
     if (ArgNum >= X86_MAX_GPR_ARGS) {
-      return Variable::NoRegister;
+      return RegNumT::NoRegister;
     }
     static const RegisterSet::AllRegisters GprForArgNum[] = {
         RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
@@ -752,7 +746,7 @@ public:
     static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
                   "Mismatch between MAX_GPR_ARGS and GprForArgNum.");
     assert(Ty == IceType_i64 || Ty == IceType_i32);
-    return static_cast<int32_t>(getGprForType(Ty, GprForArgNum[ArgNum]));
+    return getGprForType(Ty, GprForArgNum[ArgNum]);
   }
 
   /// The number of bits in a byte
index ee2e5b0..c0bafd3 100644 (file)
@@ -94,8 +94,9 @@ public:
   SizeT getNumRegisters() const override {
     return Traits::RegisterSet::Reg_NUM;
   }
-  Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
-  IceString getRegName(SizeT RegNum, Type Ty) const override;
+  Variable *getPhysicalRegister(RegNumT RegNum,
+                                Type Ty = IceType_void) override;
+  IceString getRegName(RegNumT RegNum, Type Ty) const override;
   static IceString getRegClassName(RegClass C) {
     auto ClassNum = static_cast<RegClassX86>(C);
     assert(ClassNum < RCX86_NUM);
@@ -131,16 +132,17 @@ public:
     return TypeToRegisterSetUnfiltered[RC];
   }
 
-  const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
-    assert(Reg < Traits::RegisterSet::Reg_NUM);
+  const llvm::SmallBitVector &
+  getAliasesForRegister(RegNumT Reg) const override {
+    Reg.assertIsValid();
     return RegisterAliases[Reg];
   }
 
   bool hasFramePointer() const override { return IsEbpBasedFrame; }
   void setHasFramePointer() override { IsEbpBasedFrame = true; }
-  SizeT getStackReg() const override { return Traits::StackPtr; }
-  SizeT getFrameReg() const override { return Traits::FramePtr; }
-  SizeT getFrameOrStackReg() const override {
+  RegNumT getStackReg() const override { return Traits::StackPtr; }
+  RegNumT getFrameReg() const override { return Traits::FramePtr; }
+  RegNumT getFrameOrStackReg() const override {
     return IsEbpBasedFrame ? getFrameReg() : getStackReg();
   }
   size_t typeWidthInBytesOnStack(Type Ty) const override {
@@ -218,7 +220,7 @@ public:
   X86Address stackVarToAsmOperand(const Variable *Var) const;
 
   InstructionSetEnum getInstructionSet() const { return InstructionSet; }
-  Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
+  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
 
 protected:
   const bool NeedSandboxing;
@@ -387,8 +389,8 @@ protected:
   };
   using LegalMask = uint32_t;
   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
-                    int32_t RegNum = Variable::NoRegister);
-  Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
+                    RegNumT RegNum = RegNumT::NoRegister);
+  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
   /// Legalize the first source operand for use in the cmp instruction.
   Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
   /// Turn a pointer operand into a memory operand that can be used by a real
@@ -397,7 +399,7 @@ protected:
   X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
                                    bool DoLegalize = true);
 
-  Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
+  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
   static Type stackSlotType();
 
   static constexpr uint32_t NoSizeLimit = 0;
@@ -413,23 +415,22 @@ protected:
   static Type firstTypeThatFitsSize(uint32_t Size,
                                     uint32_t MaxSize = NoSizeLimit);
 
-  Variable *copyToReg8(Operand *Src, int32_t RegNum = Variable::NoRegister);
-  Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
+  Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
 
   /// Returns a register containing all zeros, without affecting the FLAGS
   /// register, using the best instruction for the type.
-  Variable *makeZeroedRegister(Type Ty, int32_t RegNum = Variable::NoRegister);
+  Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
 
   /// \name Returns a vector in a register with the given constant entries.
   /// @{
-  Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
-  Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister);
+  Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
   Variable *makeVectorOfMinusOnes(Type Ty,
-                                  int32_t RegNum = Variable::NoRegister);
+                                  RegNumT RegNum = RegNumT::NoRegister);
   Variable *makeVectorOfHighOrderBits(Type Ty,
-                                      int32_t RegNum = Variable::NoRegister);
-  Variable *makeVectorOfFabsMask(Type Ty,
-                                 int32_t RegNum = Variable::NoRegister);
+                                      RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
   /// @}
 
   /// Return a memory operand corresponding to a stack allocated Variable.
@@ -437,7 +438,7 @@ protected:
                                               uint32_t Offset = 0);
 
   void
-  makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
+  makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
                                 const llvm::SmallBitVector &ExcludeRegisters,
                                 uint64_t Salt) const override;
 
@@ -675,7 +676,7 @@ protected:
   /// infinite register allocation weight, and returned through the in/out Dest
   /// argument.
   typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
-                                    int32_t RegNum = Variable::NoRegister) {
+                                    RegNumT RegNum = RegNumT::NoRegister) {
     if (Dest == nullptr)
       Dest = makeReg(Src0->getType(), RegNum);
     AutoMemorySandboxer<> _(this, &Dest, &Src0);
@@ -999,10 +1000,9 @@ protected:
 
   /// Randomize a given immediate operand
   Operand *randomizeOrPoolImmediate(Constant *Immediate,
-                                    int32_t RegNum = Variable::NoRegister);
-  X86OperandMem *
-  randomizeOrPoolImmediate(X86OperandMem *MemOperand,
-                           int32_t RegNum = Variable::NoRegister);
+                                    RegNumT RegNum = RegNumT::NoRegister);
+  X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
+                                          RegNumT RegNum = RegNumT::NoRegister);
   bool RandomizationPoolingPaused = false;
 
 private:
index 6e338e6..7f2b349 100644 (file)
@@ -377,6 +377,7 @@ TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func)
 
 template <typename TraitsType>
 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) {
+  RegNumT::setLimit(Traits::RegisterSet::Reg_NUM);
   Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet,
                           &RegisterAliases);
   for (size_t i = 0; i < TypeToRegisterSet.size(); ++i)
@@ -842,13 +843,13 @@ bool TargetX86Base<TraitsType>::doBranchOpt(Inst *I, const CfgNode *NextNode) {
 }
 
 template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::getPhysicalRegister(SizeT RegNum,
+Variable *TargetX86Base<TraitsType>::getPhysicalRegister(RegNumT RegNum,
                                                          Type Ty) {
   if (Ty == IceType_void)
     Ty = IceType_i32;
   if (PhysicalRegisters[Ty].empty())
     PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM);
-  assert(RegNum < PhysicalRegisters[Ty].size());
+  assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
   Variable *Reg = PhysicalRegisters[Ty][RegNum];
   if (Reg == nullptr) {
     Reg = Func->makeVariable(Ty);
@@ -861,12 +862,12 @@ Variable *TargetX86Base<TraitsType>::getPhysicalRegister(SizeT RegNum,
     // Don't bother tracking the live range of a named physical register.
     Reg->setIgnoreLiveness();
   }
-  assert(Traits::getGprForType(Ty, RegNum) == static_cast<int32_t>(RegNum));
+  assert(Traits::getGprForType(Ty, RegNum) == RegNum);
   return Reg;
 }
 
 template <typename TraitsType>
-IceString TargetX86Base<TraitsType>::getRegName(SizeT RegNum, Type Ty) const {
+IceString TargetX86Base<TraitsType>::getRegName(RegNumT RegNum, Type Ty) const {
   return Traits::getRegName(Traits::getGprForType(Ty, RegNum));
 }
 
@@ -889,8 +890,8 @@ void TargetX86Base<TraitsType>::emitVariable(const Variable *Var) const {
                              Func->getFunctionName());
   }
   const int32_t Offset = Var->getStackOffset();
-  int32_t BaseRegNum = Var->getBaseRegNum();
-  if (BaseRegNum == Variable::NoRegister)
+  auto BaseRegNum = Var->getBaseRegNum();
+  if (BaseRegNum == RegNumT::NoRegister)
     BaseRegNum = getFrameOrStackReg();
   // Print in the form "Offset(%reg)", taking care that:
   //   - Offset is never printed when it is 0
@@ -919,8 +920,8 @@ TargetX86Base<TraitsType>::stackVarToAsmOperand(const Variable *Var) const {
                              Func->getFunctionName());
   }
   int32_t Offset = Var->getStackOffset();
-  int32_t BaseRegNum = Var->getBaseRegNum();
-  if (Var->getBaseRegNum() == Variable::NoRegister)
+  auto BaseRegNum = Var->getBaseRegNum();
+  if (Var->getBaseRegNum() == RegNumT::NoRegister)
     BaseRegNum = getFrameOrStackReg();
   return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset,
                     AssemblerFixup::NoFixup);
@@ -1014,20 +1015,18 @@ void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) {
   uint32_t NumCallee = 0;
   size_t PreservedRegsSizeBytes = 0;
   llvm::SmallBitVector Pushed(CalleeSaves.size());
-  for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
-    const int32_t Canonical = Traits::getBaseReg(i);
+  for (RegNumT i : RegNumBVIter(CalleeSaves)) {
+    const auto Canonical = Traits::getBaseReg(i);
     assert(Canonical == Traits::getBaseReg(Canonical));
-    if (CalleeSaves[i] && RegsUsed[i]) {
+    if (RegsUsed[i]) {
       Pushed[Canonical] = true;
     }
   }
-  for (SizeT i = 0; i < Pushed.size(); ++i) {
-    if (!Pushed[i])
-      continue;
-    assert(static_cast<int32_t>(i) == Traits::getBaseReg(i));
+  for (RegNumT RegNum : RegNumBVIter(Pushed)) {
+    assert(RegNum == Traits::getBaseReg(RegNum));
     ++NumCallee;
     PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType);
-    _push_reg(getPhysicalRegister(i, Traits::WordType));
+    _push_reg(getPhysicalRegister(RegNum, Traits::WordType));
   }
   Ctx->statsUpdateRegistersSaved(NumCallee);
 
@@ -1124,20 +1123,20 @@ void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) {
   for (Variable *Arg : Args) {
     // Skip arguments passed in registers.
     if (isVectorType(Arg->getType())) {
-      if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != Variable::NoRegister) {
+      if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) {
         ++NumXmmArgs;
         continue;
       }
     } else if (isScalarFloatingType(Arg->getType())) {
       if (Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-          Traits::getRegisterForXmmArgNum(NumXmmArgs) != Variable::NoRegister) {
+          Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) {
         ++NumXmmArgs;
         continue;
       }
     } else {
       assert(isScalarIntegerType(Arg->getType()));
       if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) !=
-          Variable::NoRegister) {
+          RegNumT::NoRegister) {
         ++NumGPRArgs;
         continue;
       }
@@ -1275,9 +1274,10 @@ void TargetX86Base<TraitsType>::addEpilog(CfgNode *Node) {
       getRegisterSet(RegSet_CalleeSave, RegSet_None);
   llvm::SmallBitVector Popped(CalleeSaves.size());
   for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) {
-    if (static_cast<SizeT>(i) == getFrameReg() && IsEbpBasedFrame)
+    const auto RegNum = RegNumT::fromInt(i);
+    if (RegNum == getFrameReg() && IsEbpBasedFrame)
       continue;
-    const SizeT Canonical = Traits::getBaseReg(i);
+    const RegNumT Canonical = Traits::getBaseReg(RegNum);
     if (CalleeSaves[i] && RegsUsed[i]) {
       Popped[Canonical] = true;
     }
@@ -1285,8 +1285,9 @@ void TargetX86Base<TraitsType>::addEpilog(CfgNode *Node) {
   for (int32_t i = Popped.size() - 1; i >= 0; --i) {
     if (!Popped[i])
       continue;
-    assert(i == Traits::getBaseReg(i));
-    _pop(getPhysicalRegister(i, Traits::WordType));
+    const auto RegNum = RegNumT::fromInt(i);
+    assert(RegNum == Traits::getBaseReg(RegNum));
+    _pop(getPhysicalRegister(RegNum, Traits::WordType));
   }
 
   if (!NeedSandboxing) {
@@ -1475,10 +1476,10 @@ void TargetX86Base<TraitsType>::lowerArguments() {
     Variable *Arg = Args[i];
     Type Ty = Arg->getType();
     Variable *RegisterArg = nullptr;
-    int32_t RegNum = Variable::NoRegister;
+    auto RegNum = RegNumT::NoRegister;
     if (isVectorType(Ty)) {
       RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs);
-      if (RegNum == Variable::NoRegister) {
+      if (RegNum == RegNumT::NoRegister) {
         XmmSlotsRemain = false;
         continue;
       }
@@ -1489,7 +1490,7 @@ void TargetX86Base<TraitsType>::lowerArguments() {
         continue;
       }
       RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs);
-      if (RegNum == Variable::NoRegister) {
+      if (RegNum == RegNumT::NoRegister) {
         XmmSlotsRemain = false;
         continue;
       }
@@ -1497,14 +1498,14 @@ void TargetX86Base<TraitsType>::lowerArguments() {
       RegisterArg = Func->makeVariable(Ty);
     } else if (isScalarIntegerType(Ty)) {
       RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs);
-      if (RegNum == Variable::NoRegister) {
+      if (RegNum == RegNumT::NoRegister) {
         GprSlotsRemain = false;
         continue;
       }
       ++NumGprArgs;
       RegisterArg = Func->makeVariable(Ty);
     }
-    assert(RegNum != Variable::NoRegister);
+    assert(RegNum != RegNumT::NoRegister);
     assert(RegisterArg != nullptr);
     // Replace Arg in the argument list with the home register. Then generate
     // an instruction in the prolog to copy the home register to the assigned
@@ -2193,8 +2194,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
     // div and idiv are the few arithmetic operators that do not allow
     // immediates as the operand.
     Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
-    uint32_t Eax;
-    uint32_t Edx;
+    RegNumT Eax;
+    RegNumT Edx;
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for udiv");
@@ -2283,8 +2284,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
     break;
   case InstArithmetic::Urem: {
     Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
-    uint32_t Eax;
-    uint32_t Edx;
+    RegNumT Eax;
+    RegNumT Edx;
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for urem");
@@ -2352,8 +2353,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
       }
     }
     Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
-    uint32_t Eax;
-    uint32_t Edx;
+    RegNumT Eax;
+    RegNumT Edx;
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for srem");
@@ -2490,15 +2491,15 @@ void TargetX86Base<TraitsType>::lowerCall(const InstCall *Instr) {
     // The PNaCl ABI requires the width of arguments to be at least 32 bits.
     assert(typeWidthInBytes(Ty) >= 4);
     if (isVectorType(Ty) && (Traits::getRegisterForXmmArgNum(XmmArgs.size()) !=
-                             Variable::NoRegister)) {
+                             RegNumT::NoRegister)) {
       XmmArgs.push_back(Arg);
     } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
                (Traits::getRegisterForXmmArgNum(XmmArgs.size()) !=
-                Variable::NoRegister)) {
+                RegNumT::NoRegister)) {
       XmmArgs.push_back(Arg);
     } else if (isScalarIntegerType(Ty) &&
                (Traits::getRegisterForGprArgNum(Ty, GprArgs.size()) !=
-                Variable::NoRegister)) {
+                RegNumT::NoRegister)) {
       GprArgs.emplace_back(Ty, Arg);
     } else {
       // Place on stack.
@@ -4274,7 +4275,7 @@ void TargetX86Base<TraitsType>::lowerAtomicCmpxchg(Variable *DestPrev,
     _mov(DestHi, T_edx);
     return;
   }
-  int32_t Eax;
+  RegNumT Eax;
   switch (Ty) {
   default:
     llvm::report_fatal_error("Bad type for cmpxchg");
@@ -4545,7 +4546,7 @@ void TargetX86Base<TraitsType>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
     return;
   }
   X86OperandMem *Addr = formMemoryOperand(Ptr, Ty);
-  int32_t Eax;
+  RegNumT Eax;
   switch (Ty) {
   default:
     llvm::report_fatal_error("Bad type for atomicRMW");
@@ -5484,7 +5485,7 @@ void TargetX86Base<TraitsType>::doMockBoundsCheck(Operand *Opnd) {
   // We use lowerStore() to copy out-args onto the stack.  This creates a memory
   // operand with the stack pointer as the base register.  Don't do bounds
   // checks on that.
-  if (Var->getRegNum() == static_cast<int32_t>(getStackReg()))
+  if (Var->getRegNum() == getStackReg())
     return;
 
   auto *Label = InstX86Label::create(Func, this);
@@ -6506,7 +6507,7 @@ uint32_t TargetX86Base<TraitsType>::getCallStackArgumentsSizeBytes(
 
 template <typename TraitsType>
 Variable *TargetX86Base<TraitsType>::makeZeroedRegister(Type Ty,
-                                                        int32_t RegNum) {
+                                                        RegNumT RegNum) {
   Variable *Reg = makeReg(Ty, RegNum);
   switch (Ty) {
   case IceType_i1:
@@ -6541,13 +6542,13 @@ Variable *TargetX86Base<TraitsType>::makeZeroedRegister(Type Ty,
 
 template <typename TraitsType>
 Variable *TargetX86Base<TraitsType>::makeVectorOfZeros(Type Ty,
-                                                       int32_t RegNum) {
+                                                       RegNumT RegNum) {
   return makeZeroedRegister(Ty, RegNum);
 }
 
 template <typename TraitsType>
 Variable *TargetX86Base<TraitsType>::makeVectorOfMinusOnes(Type Ty,
-                                                           int32_t RegNum) {
+                                                           RegNumT RegNum) {
   Variable *MinusOnes = makeReg(Ty, RegNum);
   // Insert a FakeDef so the live range of MinusOnes is not overestimated.
   Context.insert<InstFakeDef>(MinusOnes);
@@ -6563,7 +6564,7 @@ Variable *TargetX86Base<TraitsType>::makeVectorOfMinusOnes(Type Ty,
 }
 
 template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, RegNumT RegNum) {
   Variable *Dest = makeVectorOfZeros(Ty, RegNum);
   Variable *MinusOne = makeVectorOfMinusOnes(Ty);
   _psub(Dest, MinusOne);
@@ -6572,7 +6573,7 @@ Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, int32_t RegNum) {
 
 template <typename TraitsType>
 Variable *TargetX86Base<TraitsType>::makeVectorOfHighOrderBits(Type Ty,
-                                                               int32_t RegNum) {
+                                                               RegNumT RegNum) {
   assert(Ty == IceType_v4i32 || Ty == IceType_v4f32 || Ty == IceType_v8i16 ||
          Ty == IceType_v16i8);
   if (Ty == IceType_v4f32 || Ty == IceType_v4i32 || Ty == IceType_v8i16) {
@@ -6600,7 +6601,7 @@ Variable *TargetX86Base<TraitsType>::makeVectorOfHighOrderBits(Type Ty,
 // TODO: above, to represent vector constants in memory.
 template <typename TraitsType>
 Variable *TargetX86Base<TraitsType>::makeVectorOfFabsMask(Type Ty,
-                                                          int32_t RegNum) {
+                                                          RegNumT RegNum) {
   Variable *Reg = makeVectorOfMinusOnes(Ty, RegNum);
   _psrl(Reg, Ctx->getConstantInt8(1));
   return Reg;
@@ -6612,7 +6613,7 @@ TargetX86Base<TraitsType>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
                                                         uint32_t Offset) {
   // Ensure that Loc is a stack slot.
   assert(Slot->mustNotHaveReg());
-  assert(Slot->getRegNum() == Variable::NoRegister);
+  assert(Slot->getRegNum() == RegNumT::NoRegister);
   // Compute the location of Loc in memory.
   // TODO(wala,stichnot): lea should not
   // be required. The address of the stack slot is known at compile time
@@ -6653,7 +6654,7 @@ TargetX86Base<TraitsType>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
 /// is a convenient way to prevent ah/bh/ch/dh from being an (invalid) argument
 /// to the pinsrb instruction.
 template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, RegNumT RegNum) {
   Type Ty = Src->getType();
   assert(isScalarIntegerType(Ty));
   assert(Ty != IceType_i1);
@@ -6688,7 +6689,7 @@ Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, int32_t RegNum) {
 /// Helper for legalize() to emit the right code to lower an operand to a
 /// register of the appropriate type.
 template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, RegNumT RegNum) {
   Type Ty = Src->getType();
   Variable *Reg = makeReg(Ty, RegNum);
   if (isVectorType(Ty)) {
@@ -6701,7 +6702,7 @@ Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, int32_t RegNum) {
 
 template <typename TraitsType>
 Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
-                                             int32_t RegNum) {
+                                             RegNumT RegNum) {
   const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi();
   const Type Ty = From->getType();
   // Assert that a physical register is allowed. To date, all calls to
@@ -6712,14 +6713,14 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
   // If we're asking for a specific physical register, make sure we're not
   // allowing any other operand kinds. (This could be future work, e.g. allow
   // the shl shift amount to be either an immediate or in ecx.)
-  assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg);
+  assert(RegNum == RegNumT::NoRegister || Allowed == Legal_Reg);
 
   // Substitute with an available infinite-weight variable if possible.  Only do
   // this when we are not asking for a specific register, and when the
   // substitution is not locked to a specific register, and when the types
   // match, in order to capture the vast majority of opportunities and avoid
   // corner cases in the lowering.
-  if (RegNum == Variable::NoRegister) {
+  if (RegNum == RegNumT::NoRegister) {
     if (Variable *Subst = getContext().availabilityGet(From)) {
       // At this point we know there is a potential substitution available.
       if (Subst->mustHaveReg() && !Subst->hasReg()) {
@@ -6780,7 +6781,7 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
     // register in x86-64.
     if (Traits::Is64Bit) {
       if (llvm::isa<ConstantInteger64>(Const)) {
-        if (RegNum != Variable::NoRegister) {
+        if (RegNum != RegNumT::NoRegister) {
           assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
         }
         return copyToReg(Const, RegNum);
@@ -6863,7 +6864,7 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
       _lea(NewVar, Mem);
       From = NewVar;
     } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
-               (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
+               (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
       From = copyToReg(From, RegNum);
     }
     return From;
@@ -6876,14 +6877,14 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
 /// Provide a trivial wrapper to legalize() for this common usage.
 template <typename TraitsType>
 Variable *TargetX86Base<TraitsType>::legalizeToReg(Operand *From,
-                                                   int32_t RegNum) {
+                                                   RegNumT RegNum) {
   return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
 }
 
 /// Legalize undef values to concrete values.
 template <typename TraitsType>
 Operand *TargetX86Base<TraitsType>::legalizeUndef(Operand *From,
-                                                  int32_t RegNum) {
+                                                  RegNumT RegNum) {
   Type Ty = From->getType();
   if (llvm::isa<ConstantUndef>(From)) {
     // Lower undefs to zero.  Another option is to lower undefs to an
@@ -6962,11 +6963,11 @@ TargetX86Base<TraitsType>::formMemoryOperand(Operand *Opnd, Type Ty,
 }
 
 template <typename TraitsType>
-Variable *TargetX86Base<TraitsType>::makeReg(Type Type, int32_t RegNum) {
+Variable *TargetX86Base<TraitsType>::makeReg(Type Type, RegNumT RegNum) {
   // There aren't any 64-bit integer registers for x86-32.
   assert(Traits::Is64Bit || Type != IceType_i64);
   Variable *Reg = Func->makeVariable(Type);
-  if (RegNum == Variable::NoRegister)
+  if (RegNum == RegNumT::NoRegister)
     Reg->setMustHaveReg();
   else
     Reg->setRegNum(RegNum);
@@ -7009,7 +7010,7 @@ template <typename TraitsType> void TargetX86Base<TraitsType>::postLower() {
 
 template <typename TraitsType>
 void TargetX86Base<TraitsType>::makeRandomRegisterPermutation(
-    llvm::SmallVectorImpl<int32_t> &Permutation,
+    llvm::SmallVectorImpl<RegNumT> &Permutation,
     const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
   Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation,
                                         ExcludeRegisters, Salt);
@@ -7070,7 +7071,7 @@ void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const {
 template <typename TraitsType>
 Operand *
 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate,
-                                                    int32_t RegNum) {
+                                                    RegNumT RegNum) {
   assert(llvm::isa<ConstantInteger32>(Immediate) ||
          llvm::isa<ConstantRelocatable>(Immediate));
   if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
@@ -7155,7 +7156,7 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate,
 template <typename TraitsType>
 typename TargetX86Base<TraitsType>::X86OperandMem *
 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
-                                                    int32_t RegNum) {
+                                                    RegNumT RegNum) {
   assert(MemOperand);
   if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
       RandomizationPoolingPaused == true) {
@@ -7240,7 +7241,7 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
     // phi lowering, we should not ask for new physical registers in
     // general. However, if we do meet Memory Operand during phi lowering,
     // we should not blind or pool the immediates for now.
-    if (RegNum != Variable::NoRegister)
+    if (RegNum != RegNumT::NoRegister)
       return MemOperand;
     Variable *RegTemp = makeReg(IceType_i32);
     IceString Label;