Subzero: Avoid explicit references to RegNumT sentinel value.

There are many occurrences of if (RegNum == RegNumT::NoRegister).

This patch eliminates NoRegister and provides a simpler mechanism for declaring and testing RegNumT values to see if they are undefined.

BUG= none
R=stichnot@chromium.org

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

Patch from Reed Kotler <rkotlerimgtec@gmail.com>.
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
index 5d53afd..c939246 100644
--- a/src/IceInstARM32.h
+++ b/src/IceInstARM32.h
@@ -361,7 +361,7 @@
 private:
   StackVariable(Type Ty, SizeT Index)
       : Variable(StackVariableKind, Ty, Index) {}
-  RegNumT BaseRegNum = RegNumT::NoRegister;
+  RegNumT BaseRegNum;
 };
 
 /// Base class for ARM instructions. While most ARM instructions can be
diff --git a/src/IceInstX86BaseImpl.h b/src/IceInstX86BaseImpl.h
index 6a087e8..b80a169 100644
--- a/src/IceInstX86BaseImpl.h
+++ b/src/IceInstX86BaseImpl.h
@@ -1987,8 +1987,7 @@
     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, RegNumT::NoRegister)
-        ->emit(Func);
+    Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())->emit(Func);
   } else {
     Src0->emit(Func);
   }
@@ -2025,7 +2024,7 @@
          InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
   const Operand *NewSrc = Src;
   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
-    auto NewRegNum = RegNumT::NoRegister;
+    RegNumT NewRegNum;
     if (SrcVar->hasReg())
       NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
     if (SrcTy != DestTy)
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index ada1606..73b0958 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -86,7 +86,6 @@
   return true;
 }
 
-const RegNumT RegNumT::NoRegister(RegNumT::NoRegisterValue);
 RegNumT::BaseType RegNumT::Limit = 0;
 
 bool operator<(const RegWeight &A, const RegWeight &B) {
@@ -201,7 +200,7 @@
   Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
       Variable(kVariable, Ty, Number);
   V->NameIndex = NameIndex;
-  V->RegNum = NewRegNum == RegNumT::NoRegister ? RegNum : NewRegNum;
+  V->RegNum = NewRegNum.hasValue() ? NewRegNum : RegNum;
   V->StackOffset = StackOffset;
   return V;
 }
diff --git a/src/IceOperand.h b/src/IceOperand.h
index a203086..9b46e35 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -403,11 +403,11 @@
 };
 
 /// 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.
+/// value if no register is assigned. 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;
@@ -441,7 +441,9 @@
   // 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 */;
+
+  bool hasValue() const { return Value != NoRegisterValue; }
+  bool hasNoValue() const { return !hasValue(); }
 
 private:
   BaseType Value = NoRegisterValue;
@@ -646,14 +648,14 @@
     return "lv$" + getName(Func);
   }
 
-  bool hasReg() const { return getRegNum() != RegNumT::NoRegister; }
+  bool hasReg() const { return getRegNum().hasValue(); }
   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() != RegNumT::NoRegister; }
+  bool hasRegTmp() const { return getRegNumTmp().hasValue(); }
   RegNumT getRegNumTmp() const { return RegNumTmp; }
   void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; }
 
@@ -702,7 +704,7 @@
   /// primarily for syntactic correctness of textual assembly emission. Note
   /// that only basic information is copied, in particular not IsArgument,
   /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
-  /// VarsReal.  If NewRegNum!=NoRegister, then that register assignment is made
+  /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made
   /// instead of copying the existing assignment.
   const Variable *asType(Type Ty, RegNumT NewRegNum) const;
 
@@ -711,7 +713,7 @@
   void dump(const Cfg *Func, Ostream &Str) const override;
 
   /// Return reg num of base register, if different from stack/frame register.
-  virtual RegNumT getBaseRegNum() const { return RegNumT::NoRegister; }
+  virtual RegNumT getBaseRegNum() const { return RegNumT(); }
 
   static bool classof(const Operand *Operand) {
     OperandKind Kind = Operand->getKind();
@@ -741,13 +743,12 @@
   bool IsRematerializable = false;
   RegRequirement RegRequirement = RR_MayHaveRegister;
   RegClass RegisterClass;
-  /// RegNum is the allocated register, or NoRegister if it isn't
-  /// register-allocated.
-  RegNumT RegNum = RegNumT::NoRegister;
+  /// RegNum is the allocated register, (as long as RegNum.hasValue() is true).
+  RegNumT RegNum;
   /// RegNumTmp is the tentative assignment during register allocation.
-  RegNumT RegNumTmp = RegNumT::NoRegister;
+  RegNumT RegNumTmp;
   /// StackOffset is the canonical location on stack (only if
-  /// RegNum==NoRegister || IsArgument).
+  /// RegNum.hasNoValue() || IsArgument).
   int32_t StackOffset = 0;
   LiveRange Live;
   /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp
index f59cb3c..993dc44 100644
--- a/src/IceRegAlloc.cpp
+++ b/src/IceRegAlloc.cpp
@@ -502,7 +502,7 @@
 // not appear within the current Variable's live range.
 void LinearScan::findRegisterPreference(IterationState &Iter) {
   Iter.Prefer = nullptr;
-  Iter.PreferReg = RegNumT::NoRegister;
+  Iter.PreferReg = RegNumT();
   Iter.AllowOverlap = false;
 
   if (!FindPreference)
@@ -738,7 +738,7 @@
         --RegUses[RegAlias];
         assert(RegUses[RegAlias] >= 0);
       }
-      Item->setRegNumTmp(RegNumT::NoRegister);
+      Item->setRegNumTmp(RegNumT());
       moveItem(Active, Index, Handled);
       Evicted.push_back(Item);
     }
@@ -756,7 +756,7 @@
     // instructions.
     if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) {
       dumpLiveRangeTrace("Evicting I   ", Item);
-      Item->setRegNumTmp(RegNumT::NoRegister);
+      Item->setRegNumTmp(RegNumT());
       moveItem(Inactive, Index, Handled);
       Evicted.push_back(Item);
     }
diff --git a/src/IceRegAlloc.h b/src/IceRegAlloc.h
index 299d709..67f4137 100644
--- a/src/IceRegAlloc.h
+++ b/src/IceRegAlloc.h
@@ -58,7 +58,7 @@
     IterationState() = default;
     Variable *Cur = nullptr;
     Variable *Prefer = nullptr;
-    RegNumT PreferReg = RegNumT::NoRegister;
+    RegNumT PreferReg;
     bool AllowOverlap = false;
     llvm::SmallBitVector RegMask;
     llvm::SmallBitVector RegMaskUnfiltered;
diff --git a/src/IceRegistersARM32.h b/src/IceRegistersARM32.h
index 6e3c562..8941a9e 100644
--- a/src/IceRegistersARM32.h
+++ b/src/IceRegistersARM32.h
@@ -104,7 +104,7 @@
 
 static inline void assertValidRegNum(RegNumT RegNum) {
   (void)RegNum;
-  assert(RegNum != RegNumT::NoRegister);
+  assert(RegNum.hasValue());
 }
 
 static inline bool isGPRegister(RegNumT RegNum) {
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 0b12bc6..85e0a65 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -1183,7 +1183,7 @@
   assert(!Var->isRematerializable());
   int32_t Offset = Var->getStackOffset();
   auto BaseRegNum = Var->getBaseRegNum();
-  if (BaseRegNum == RegNumT::NoRegister) {
+  if (BaseRegNum.hasNoValue()) {
     BaseRegNum = getFrameOrStackReg();
   }
   const Type VarTy = Var->getType();
@@ -5816,7 +5816,7 @@
   assert(Allowed & Legal_Reg);
 
   // Copied ipsis literis from TargetX86Base<Machine>.
-  if (RegNum == RegNumT::NoRegister) {
+  if (RegNum.hasNoValue()) {
     if (Variable *Subst = getContext().availabilityGet(From)) {
       // At this point we know there is a potential substitution available.
       if (!Subst->isRematerializable() && Subst->mustHaveReg() &&
@@ -6018,7 +6018,7 @@
     //   register, or
     //   RegNum is required and Var->getRegNum() doesn't match.
     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
-        (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
+        (RegNum.hasValue() && (RegNum != Var->getRegNum()))) {
       From = copyToReg(From, RegNum);
     }
     return From;
@@ -6085,12 +6085,12 @@
 Variable *TargetARM32::makeReg(Type Type, RegNumT RegNum) {
   // There aren't any 64-bit integer registers for ARM32.
   assert(Type != IceType_i64);
-  assert(AllowTemporaryWithNoReg || RegNum != RegNumT::NoRegister);
+  assert(AllowTemporaryWithNoReg || RegNum.hasValue());
   Variable *Reg = Func->makeVariable(Type);
-  if (RegNum == RegNumT::NoRegister)
-    Reg->setMustHaveReg();
-  else
+  if (RegNum.hasValue())
     Reg->setRegNum(RegNum);
+  else
+    Reg->setMustHaveReg();
   return Reg;
 }
 
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 267c766..e457127 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -174,10 +174,10 @@
   };
 
   using LegalMask = uint32_t;
-  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
-                    RegNumT RegNum = RegNumT::NoRegister);
-  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+                    RegNumT RegNum = RegNumT());
+  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
 
   OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const {
     assert(ShAmtImm < 32);
@@ -270,14 +270,14 @@
   OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
 
   Variable64On32 *makeI64RegPair();
-  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
   static Type stackSlotType();
-  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
   void alignRegisterPow2(Variable *Reg, uint32_t Align,
-                         RegNumT TmpRegNum = RegNumT::NoRegister);
+                         RegNumT TmpRegNum = RegNumT());
 
   /// Returns a vector in a register with the given constant entries.
-  Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
 
   void
   makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index e34dd5d..075e62c 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -360,10 +360,10 @@
   // There aren't any 64-bit integer registers for Mips32.
   assert(Type != IceType_i64);
   Variable *Reg = Func->makeVariable(Type);
-  if (RegNum == RegNumT::NoRegister)
-    Reg->setMustHaveReg();
-  else
+  if (RegNum.hasValue())
     Reg->setRegNum(RegNum);
+  else
+    Reg->setMustHaveReg();
   return Reg;
 }
 
@@ -1253,10 +1253,10 @@
     // Also try the inverse and use MVN if possible.
     // Do a movw/movt to a register.
     Variable *Reg;
-    if (RegNum == RegNumT::NoRegister)
-      Reg = makeReg(Ty, RegNum);
-    else
+    if (RegNum.hasValue())
       Reg = getPhysicalRegister(RegNum);
+    else
+      Reg = makeReg(Ty, RegNum);
     if (isInt<16>(int32_t(Value))) {
       Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty);
       Context.insert<InstFakeDef>(Zero);
@@ -1281,7 +1281,7 @@
     //   register, or
     //   RegNum is required and Var->getRegNum() doesn't match.
     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
-        (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
+        (RegNum.hasValue() && RegNum != Var->getRegNum())) {
       From = copyToReg(From, RegNum);
     }
     return From;
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 7608de1..08897e8 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -220,15 +220,15 @@
   };
   typedef uint32_t LegalMask;
   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
-                    RegNumT RegNum = RegNumT::NoRegister);
+                    RegNumT RegNum = RegNumT());
 
-  Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT());
 
-  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
 
-  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
   static Type stackSlotType();
-  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
 
   void addProlog(CfgNode *Node) override;
   void addEpilog(CfgNode *Node) override;
@@ -240,7 +240,7 @@
   Operand *loOperand(Operand *Operand);
   Operand *hiOperand(Operand *Operand);
 
-  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
 
 protected:
   explicit TargetMIPS32(Cfg *Func);
diff --git a/src/IceTargetLoweringX8632Traits.h b/src/IceTargetLoweringX8632Traits.h
index 8b5412d..2ff3d7a 100644
--- a/src/IceTargetLoweringX8632Traits.h
+++ b/src/IceTargetLoweringX8632Traits.h
@@ -375,7 +375,7 @@
 public:
   // Return a register in RegNum's alias set that is suitable for Ty.
   static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
-    assert(RegNum != RegNumT::NoRegister);
+    assert(RegNum.hasValue());
 
     if (!isScalarIntegerType(Ty)) {
       return RegNum;
@@ -686,7 +686,7 @@
     static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
                   "Inconsistency between XMM register numbers and ordinals");
     if (ArgNum >= X86_MAX_XMM_ARGS) {
-      return RegNumT::NoRegister;
+      return RegNumT();
     }
     return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
   }
@@ -695,7 +695,7 @@
     assert(Ty == IceType_i64 || Ty == IceType_i32);
     (void)Ty;
     (void)ArgNum;
-    return RegNumT::NoRegister;
+    return RegNumT();
   }
 
   /// The number of bits in a byte
diff --git a/src/IceTargetLoweringX8664.cpp b/src/IceTargetLoweringX8664.cpp
index ecf86b0..86956cd 100644
--- a/src/IceTargetLoweringX8664.cpp
+++ b/src/IceTargetLoweringX8664.cpp
@@ -419,8 +419,7 @@
     }
   }
 
-  auto RegNum = RegNumT::NoRegister;
-  auto RegNum32 = RegNumT::NoRegister;
+  RegNumT RegNum, RegNum32;
   if (T != nullptr) {
     if (T->hasReg()) {
       RegNum = Traits::getGprForType(IceType_i64, T->getRegNum());
diff --git a/src/IceTargetLoweringX8664Traits.h b/src/IceTargetLoweringX8664Traits.h
index 18e054a..0ee1a69 100644
--- a/src/IceTargetLoweringX8664Traits.h
+++ b/src/IceTargetLoweringX8664Traits.h
@@ -401,7 +401,7 @@
 
 public:
   static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
-    assert(RegNum != RegNumT::NoRegister);
+    assert(RegNum.hasValue());
 
     if (!isScalarIntegerType(Ty)) {
       return RegNum;
@@ -730,14 +730,14 @@
     static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
                   "Inconsistency between XMM register numbers and ordinals");
     if (ArgNum >= X86_MAX_XMM_ARGS) {
-      return RegNumT::NoRegister;
+      return RegNumT();
     }
     return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
   }
   /// Get the register for a given argument slot in the GPRs.
   static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
     if (ArgNum >= X86_MAX_GPR_ARGS) {
-      return RegNumT::NoRegister;
+      return RegNumT();
     }
     static const RegisterSet::AllRegisters GprForArgNum[] = {
         RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
diff --git a/src/IceTargetLoweringX86Base.h b/src/IceTargetLoweringX86Base.h
index c0bafd3..fd8f818 100644
--- a/src/IceTargetLoweringX86Base.h
+++ b/src/IceTargetLoweringX86Base.h
@@ -220,7 +220,7 @@
   X86Address stackVarToAsmOperand(const Variable *Var) const;
 
   InstructionSetEnum getInstructionSet() const { return InstructionSet; }
-  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
 
 protected:
   const bool NeedSandboxing;
@@ -389,8 +389,8 @@
   };
   using LegalMask = uint32_t;
   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
-                    RegNumT RegNum = RegNumT::NoRegister);
-  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT::NoRegister);
+                    RegNumT RegNum = RegNumT());
+  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
   /// 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
@@ -399,7 +399,7 @@
   X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty,
                                    bool DoLegalize = true);
 
-  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
   static Type stackSlotType();
 
   static constexpr uint32_t NoSizeLimit = 0;
@@ -415,22 +415,20 @@
   static Type firstTypeThatFitsSize(uint32_t Size,
                                     uint32_t MaxSize = NoSizeLimit);
 
-  Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
-  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT());
+  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
 
   /// Returns a register containing all zeros, without affecting the FLAGS
   /// register, using the best instruction for the type.
-  Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT());
 
   /// \name Returns a vector in a register with the given constant entries.
   /// @{
-  Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
-  Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
-  Variable *makeVectorOfMinusOnes(Type Ty,
-                                  RegNumT RegNum = RegNumT::NoRegister);
-  Variable *makeVectorOfHighOrderBits(Type Ty,
-                                      RegNumT RegNum = RegNumT::NoRegister);
-  Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT::NoRegister);
+  Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT());
+  Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT());
+  Variable *makeVectorOfMinusOnes(Type Ty, RegNumT RegNum = RegNumT());
+  Variable *makeVectorOfHighOrderBits(Type Ty, RegNumT RegNum = RegNumT());
+  Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT());
   /// @}
 
   /// Return a memory operand corresponding to a stack allocated Variable.
@@ -676,7 +674,7 @@
   /// infinite register allocation weight, and returned through the in/out Dest
   /// argument.
   typename Traits::Insts::Mov *_mov(Variable *&Dest, Operand *Src0,
-                                    RegNumT RegNum = RegNumT::NoRegister) {
+                                    RegNumT RegNum = RegNumT()) {
     if (Dest == nullptr)
       Dest = makeReg(Src0->getType(), RegNum);
     AutoMemorySandboxer<> _(this, &Dest, &Src0);
@@ -1000,9 +998,9 @@
 
   /// Randomize a given immediate operand
   Operand *randomizeOrPoolImmediate(Constant *Immediate,
-                                    RegNumT RegNum = RegNumT::NoRegister);
+                                    RegNumT RegNum = RegNumT());
   X86OperandMem *randomizeOrPoolImmediate(X86OperandMem *MemOperand,
-                                          RegNumT RegNum = RegNumT::NoRegister);
+                                          RegNumT RegNum = RegNumT());
   bool RandomizationPoolingPaused = false;
 
 private:
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index 7f2b349..cdece9c 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -891,7 +891,7 @@
   }
   const int32_t Offset = Var->getStackOffset();
   auto BaseRegNum = Var->getBaseRegNum();
-  if (BaseRegNum == RegNumT::NoRegister)
+  if (BaseRegNum.hasNoValue())
     BaseRegNum = getFrameOrStackReg();
   // Print in the form "Offset(%reg)", taking care that:
   //   - Offset is never printed when it is 0
@@ -921,7 +921,7 @@
   }
   int32_t Offset = Var->getStackOffset();
   auto BaseRegNum = Var->getBaseRegNum();
-  if (Var->getBaseRegNum() == RegNumT::NoRegister)
+  if (Var->getBaseRegNum().hasNoValue())
     BaseRegNum = getFrameOrStackReg();
   return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset,
                     AssemblerFixup::NoFixup);
@@ -1123,20 +1123,20 @@
   for (Variable *Arg : Args) {
     // Skip arguments passed in registers.
     if (isVectorType(Arg->getType())) {
-      if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) {
+      if (Traits::getRegisterForXmmArgNum(NumXmmArgs).hasValue()) {
         ++NumXmmArgs;
         continue;
       }
     } else if (isScalarFloatingType(Arg->getType())) {
       if (Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-          Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) {
+          Traits::getRegisterForXmmArgNum(NumXmmArgs).hasValue()) {
         ++NumXmmArgs;
         continue;
       }
     } else {
       assert(isScalarIntegerType(Arg->getType()));
-      if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) !=
-          RegNumT::NoRegister) {
+      if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs)
+              .hasValue()) {
         ++NumGPRArgs;
         continue;
       }
@@ -1476,10 +1476,10 @@
     Variable *Arg = Args[i];
     Type Ty = Arg->getType();
     Variable *RegisterArg = nullptr;
-    auto RegNum = RegNumT::NoRegister;
+    RegNumT RegNum;
     if (isVectorType(Ty)) {
       RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs);
-      if (RegNum == RegNumT::NoRegister) {
+      if (RegNum.hasNoValue()) {
         XmmSlotsRemain = false;
         continue;
       }
@@ -1490,7 +1490,7 @@
         continue;
       }
       RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs);
-      if (RegNum == RegNumT::NoRegister) {
+      if (RegNum.hasNoValue()) {
         XmmSlotsRemain = false;
         continue;
       }
@@ -1498,14 +1498,14 @@
       RegisterArg = Func->makeVariable(Ty);
     } else if (isScalarIntegerType(Ty)) {
       RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs);
-      if (RegNum == RegNumT::NoRegister) {
+      if (RegNum.hasNoValue()) {
         GprSlotsRemain = false;
         continue;
       }
       ++NumGprArgs;
       RegisterArg = Func->makeVariable(Ty);
     }
-    assert(RegNum != RegNumT::NoRegister);
+    assert(RegNum.hasValue());
     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
@@ -2490,16 +2490,14 @@
     const Type Ty = Arg->getType();
     // 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()) !=
-                             RegNumT::NoRegister)) {
+    if (isVectorType(Ty) &&
+        Traits::getRegisterForXmmArgNum(XmmArgs.size()).hasValue()) {
       XmmArgs.push_back(Arg);
     } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-               (Traits::getRegisterForXmmArgNum(XmmArgs.size()) !=
-                RegNumT::NoRegister)) {
+               Traits::getRegisterForXmmArgNum(XmmArgs.size()).hasValue()) {
       XmmArgs.push_back(Arg);
     } else if (isScalarIntegerType(Ty) &&
-               (Traits::getRegisterForGprArgNum(Ty, GprArgs.size()) !=
-                RegNumT::NoRegister)) {
+               Traits::getRegisterForGprArgNum(Ty, GprArgs.size()).hasValue()) {
       GprArgs.emplace_back(Ty, Arg);
     } else {
       // Place on stack.
@@ -6613,7 +6611,7 @@
                                                         uint32_t Offset) {
   // Ensure that Loc is a stack slot.
   assert(Slot->mustNotHaveReg());
-  assert(Slot->getRegNum() == RegNumT::NoRegister);
+  assert(Slot->getRegNum().hasNoValue());
   // 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
@@ -6642,7 +6640,7 @@
 ///
 /// Note #1.  On a 64-bit target, the "movb 4(%ebp), %ah" is likely not
 /// encodable, so RegNum=Reg_ah should NOT be given as an argument.  Instead,
-/// use RegNum=NoRegister and then let the caller do a separate copy into
+/// use RegNum=RegNumT() and then let the caller do a separate copy into
 /// Reg_ah.
 ///
 /// Note #2.  ConstantRelocatable operands are also put through this process
@@ -6713,14 +6711,14 @@
   // 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 == RegNumT::NoRegister || Allowed == Legal_Reg);
+  assert(RegNum.hasNoValue() || 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 == RegNumT::NoRegister) {
+  if (RegNum.hasNoValue()) {
     if (Variable *Subst = getContext().availabilityGet(From)) {
       // At this point we know there is a potential substitution available.
       if (Subst->mustHaveReg() && !Subst->hasReg()) {
@@ -6781,7 +6779,7 @@
     // register in x86-64.
     if (Traits::Is64Bit) {
       if (llvm::isa<ConstantInteger64>(Const)) {
-        if (RegNum != RegNumT::NoRegister) {
+        if (RegNum.hasValue()) {
           assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
         }
         return copyToReg(Const, RegNum);
@@ -6864,7 +6862,7 @@
       _lea(NewVar, Mem);
       From = NewVar;
     } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
-               (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) {
+               (RegNum.hasValue() && RegNum != Var->getRegNum())) {
       From = copyToReg(From, RegNum);
     }
     return From;
@@ -6967,10 +6965,10 @@
   // There aren't any 64-bit integer registers for x86-32.
   assert(Traits::Is64Bit || Type != IceType_i64);
   Variable *Reg = Func->makeVariable(Type);
-  if (RegNum == RegNumT::NoRegister)
-    Reg->setMustHaveReg();
-  else
+  if (RegNum.hasValue())
     Reg->setRegNum(RegNum);
+  else
+    Reg->setMustHaveReg();
   return Reg;
 }
 
@@ -7241,7 +7239,7 @@
     // 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 != RegNumT::NoRegister)
+    if (RegNum.hasValue())
       return MemOperand;
     Variable *RegTemp = makeReg(IceType_i32);
     IceString Label;