Subzero. Changes the Register Allocator so that it is aware of register
aliases.

BUG=
R=jvoung@chromium.org, stichnot@chromium.org

Review URL: https://codereview.chromium.org/1319203005.
diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp
index cad7fb5..ad5c2b6 100644
--- a/src/IceRegAlloc.cpp
+++ b/src/IceRegAlloc.cpp
@@ -79,7 +79,7 @@
 } // end of anonymous namespace
 
 LinearScan::LinearScan(Cfg *Func)
-    : Func(Func), Ctx(Func->getContext()),
+    : Func(Func), Ctx(Func->getContext()), Target(Func->getTarget()),
       Verbose(BuildDefs::dump() && Func->isVerbose(IceV_LinearScan)) {}
 
 // Prepare for full register allocation of all variables.  We depend on
@@ -225,6 +225,12 @@
   Inactive.clear();
   Active.clear();
 
+  SizeT NumRegs = Target->getNumRegisters();
+  RegAliases.resize(NumRegs);
+  for (SizeT Reg = 0; Reg < NumRegs; ++Reg) {
+    RegAliases[Reg] = &Target->getAliasesForRegister(Reg);
+  }
+
   switch (Kind) {
   case RAK_Unknown:
     llvm::report_fatal_error("Invalid RAK_Unknown");
@@ -295,8 +301,13 @@
       // range.  Start looking after SpillPoint gets set, i.e. once Cur's live
       // range begins.
       FOREACH_VAR_IN_INST(Var, *I) {
-        if (Var->hasRegTmp())
-          Iter.RegMask[Var->getRegNumTmp()] = false;
+        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)) {
+          Iter.RegMask[RegAlias] = false;
+        }
       }
     }
   }
@@ -307,7 +318,6 @@
   int32_t RegNum = Iter.RegMask.find_first();
   assert(RegNum != -1);
   Iter.Cur->setRegNumTmp(RegNum);
-  TargetLowering *Target = Func->getTarget();
   Variable *Preg = Target->getPhysicalRegister(RegNum, Iter.Cur->getType());
   // TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc
   // is correctly identified as !isMultiBlock(), reducing stack frame size.
@@ -340,9 +350,12 @@
     if (Moved) {
       // Decrement Item from RegUses[].
       assert(Item->hasRegTmp());
-      int32_t RegNum = Item->getRegNumTmp();
-      --RegUses[RegNum];
-      assert(RegUses[RegNum] >= 0);
+      const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
+      for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+           RegAlias = Aliases.find_next(RegAlias)) {
+        --RegUses[RegAlias];
+        assert(RegUses[RegAlias] >= 0);
+      }
     }
   }
 }
@@ -362,9 +375,12 @@
       moveItem(Inactive, Index, Active);
       // Increment Item in RegUses[].
       assert(Item->hasRegTmp());
-      int32_t RegNum = Item->getRegNumTmp();
-      assert(RegUses[RegNum] >= 0);
-      ++RegUses[RegNum];
+      const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
+      for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+           RegAlias = Aliases.find_next(RegAlias)) {
+        assert(RegUses[RegAlias] >= 0);
+        ++RegUses[RegAlias];
+      }
     }
   }
 }
@@ -430,17 +446,20 @@
 // the current range.
 void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) {
   for (const Variable *Item : Inactive) {
-    if (Item->rangeOverlaps(Iter.Cur)) {
-      int32_t RegNum = Item->getRegNumTmp();
+    if (!Item->rangeOverlaps(Iter.Cur))
+      continue;
+    const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
+    for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+         RegAlias = Aliases.find_next(RegAlias)) {
       // Don't assert(Free[RegNum]) because in theory (though probably never in
       // practice) there could be two inactive variables that were marked with
       // AllowOverlap.
-      Iter.Free[RegNum] = false;
+      Iter.Free[RegAlias] = false;
       // Disable AllowOverlap if an Inactive variable, which is not Prefer,
       // shares Prefer's register, and has a definition within Cur's live
       // range.
       if (Iter.AllowOverlap && Item != Iter.Prefer &&
-          RegNum == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) {
+          RegAlias == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) {
         Iter.AllowOverlap = false;
         dumpDisableOverlap(Func, Item, "Inactive");
       }
@@ -459,15 +478,19 @@
     if (Iter.Cur->rangeEndsBefore(Item))
       break;
     if (Item->rangeOverlaps(Iter.Cur)) {
-      int32_t ItemReg = Item->getRegNum(); // Note: not getRegNumTmp()
-      Iter.Weights[ItemReg].setWeight(RegWeight::Inf);
-      Iter.Free[ItemReg] = false;
-      Iter.PrecoloredUnhandledMask[ItemReg] = true;
-      // Disable Iter.AllowOverlap if the preferred register is one of these
-      // pre-colored unhandled overlapping ranges.
-      if (Iter.AllowOverlap && ItemReg == Iter.PreferReg) {
-        Iter.AllowOverlap = false;
-        dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
+      const llvm::SmallBitVector &Aliases =
+          *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
+      for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+           RegAlias = Aliases.find_next(RegAlias)) {
+        Iter.Weights[RegAlias].setWeight(RegWeight::Inf);
+        Iter.Free[RegAlias] = false;
+        Iter.PrecoloredUnhandledMask[RegAlias] = true;
+        // Disable Iter.AllowOverlap if the preferred register is one of these
+        // pre-colored unhandled overlapping ranges.
+        if (Iter.AllowOverlap && RegAlias == Iter.PreferReg) {
+          Iter.AllowOverlap = false;
+          dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
+        }
       }
     }
   }
@@ -479,8 +502,12 @@
   assert(Cur->getRegNumTmp() == RegNum);
   dumpLiveRangeTrace("Precoloring  ", Cur);
   Active.push_back(Cur);
-  assert(RegUses[RegNum] >= 0);
-  ++RegUses[RegNum];
+  const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
+  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+       RegAlias = Aliases.find_next(RegAlias)) {
+    assert(RegUses[RegAlias] >= 0);
+    ++RegUses[RegAlias];
+  }
   assert(!UnhandledPrecolored.empty());
   assert(UnhandledPrecolored.back() == Cur);
   UnhandledPrecolored.pop_back();
@@ -489,8 +516,12 @@
 void LinearScan::allocatePreferredRegister(IterationState &Iter) {
   Iter.Cur->setRegNumTmp(Iter.PreferReg);
   dumpLiveRangeTrace("Preferring   ", Iter.Cur);
-  assert(RegUses[Iter.PreferReg] >= 0);
-  ++RegUses[Iter.PreferReg];
+  const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
+  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+       RegAlias = Aliases.find_next(RegAlias)) {
+    assert(RegUses[RegAlias] >= 0);
+    ++RegUses[RegAlias];
+  }
   Active.push_back(Iter.Cur);
 }
 
@@ -498,8 +529,12 @@
   int32_t RegNum = Iter.Free.find_first();
   Iter.Cur->setRegNumTmp(RegNum);
   dumpLiveRangeTrace("Allocating   ", Iter.Cur);
-  assert(RegUses[RegNum] >= 0);
-  ++RegUses[RegNum];
+  const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
+  for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+       RegAlias = Aliases.find_next(RegAlias)) {
+    assert(RegUses[RegAlias] >= 0);
+    ++RegUses[RegAlias];
+  }
   Active.push_back(Iter.Cur);
 }
 
@@ -507,16 +542,28 @@
   // Check Active ranges.
   for (const Variable *Item : Active) {
     assert(Item->rangeOverlaps(Iter.Cur));
-    int32_t RegNum = Item->getRegNumTmp();
     assert(Item->hasRegTmp());
-    Iter.Weights[RegNum].addWeight(Item->getWeight(Func));
+    const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
+    // We add the Item's weight to each alias/subregister to represent that,
+    // 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)) {
+      Iter.Weights[RegAlias].addWeight(W);
+    }
   }
   // Same as above, but check Inactive ranges instead of Active.
   for (const Variable *Item : Inactive) {
-    int32_t RegNum = Item->getRegNumTmp();
+    if (!Item->rangeOverlaps(Iter.Cur))
+      continue;
     assert(Item->hasRegTmp());
-    if (Item->rangeOverlaps(Iter.Cur))
-      Iter.Weights[RegNum].addWeight(Item->getWeight(Func));
+    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)) {
+      Iter.Weights[RegAlias].addWeight(W);
+    }
   }
 
   // All the weights are now calculated. Find the register with smallest
@@ -548,8 +595,12 @@
       Variable *Item = Active[Index];
       if (Item->getRegNumTmp() == MinWeightIndex) {
         dumpLiveRangeTrace("Evicting     ", Item);
-        --RegUses[MinWeightIndex];
-        assert(RegUses[MinWeightIndex] >= 0);
+        const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
+        for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+             RegAlias = Aliases.find_next(RegAlias)) {
+          --RegUses[RegAlias];
+          assert(RegUses[RegAlias] >= 0);
+        }
         Item->setRegNumTmp(Variable::NoRegister);
         moveItem(Active, Index, Handled);
       }
@@ -574,8 +625,12 @@
     }
     // Assign the register to Cur.
     Iter.Cur->setRegNumTmp(MinWeightIndex);
-    assert(RegUses[MinWeightIndex] >= 0);
-    ++RegUses[MinWeightIndex];
+    const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
+    for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
+         RegAlias = Aliases.find_next(RegAlias)) {
+      assert(RegUses[RegAlias] >= 0);
+      ++RegUses[RegAlias];
+    }
     Active.push_back(Iter.Cur);
     dumpLiveRangeTrace("Allocating   ", Iter.Cur);
   }
@@ -594,7 +649,7 @@
     // is different.
     uint64_t Salt =
         (Func->getSequenceNumber() << 1) ^ (Kind == RAK_Phi ? 0u : 1u);
-    Func->getTarget()->makeRandomRegisterPermutation(
+    Target->makeRandomRegisterPermutation(
         Permutation, PreDefinedRegisters | ~RegMaskFull, Salt);
   }
 
@@ -616,8 +671,8 @@
       } else {
         Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning "
                                                     : "Assigning ")
-            << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32)
-            << "(r" << AssignedRegNum << ") to ";
+            << Target->getRegName(AssignedRegNum, IceType_i32) << "(r"
+            << AssignedRegNum << ") to ";
         Item->dump(Func);
         Str << "\n";
       }
@@ -667,7 +722,7 @@
       TargetLowering::RegSet_CallerSave;
   const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None;
   const llvm::SmallBitVector KillsMask =
-      Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude);
+      Target->getRegisterSet(RegsInclude, RegsExclude);
 
   // Allocate memory once outside the loop
   IterationState Iter;
@@ -679,8 +734,7 @@
     Unhandled.pop_back();
     dumpLiveRangeTrace("\nConsidering  ", Iter.Cur);
     Iter.RegMask =
-        RegMaskFull &
-        Func->getTarget()->getRegisterSetForType(Iter.Cur->getType());
+        RegMaskFull & Target->getRegisterSetForType(Iter.Cur->getType());
     KillsRange.trim(Iter.Cur->getLiveRange().getStart());
 
     // Check for pre-colored ranges. If Cur is pre-colored, it definitely gets
@@ -744,8 +798,8 @@
       Ostream &Str = Ctx->getStrDump();
       for (SizeT i = 0; i < Iter.RegMask.size(); ++i) {
         if (Iter.RegMask[i]) {
-          Str << Func->getTarget()->getRegName(i, IceType_i32)
-              << "(U=" << RegUses[i] << ",F=" << Iter.Free[i]
+          Str << Target->getRegName(i, IceType_i32) << "(U=" << RegUses[i]
+              << ",F=" << Iter.Free[i]
               << ",P=" << Iter.PrecoloredUnhandledMask[i] << ") ";
         }
       }
diff --git a/src/IceRegAlloc.h b/src/IceRegAlloc.h
index f681091..e2b36e5 100644
--- a/src/IceRegAlloc.h
+++ b/src/IceRegAlloc.h
@@ -96,6 +96,7 @@
 
   Cfg *const Func;
   GlobalContext *const Ctx;
+  TargetLowering *const Target;
 
   OrderedRanges Unhandled;
   /// UnhandledPrecolored is a subset of Unhandled, specially collected for
@@ -108,6 +109,9 @@
   /// currently assigned to. It can be greater than 1 as a result of
   /// AllowOverlap inference.
   llvm::SmallVector<int32_t, REGS_SIZE> RegUses;
+  // TODO(jpp): for some architectures a SmallBitVector might not be big enough.
+  // Evaluate what the performance impact on those architectures is.
+  llvm::SmallVector<const llvm::SmallBitVector *, REGS_SIZE> RegAliases;
   bool FindPreference = false;
   bool FindOverlap = false;
 
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index a1c5aad..e63ece2 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -211,6 +211,8 @@
   virtual llvm::SmallBitVector getRegisterSet(RegSetMask Include,
                                               RegSetMask Exclude) const = 0;
   virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0;
+  virtual const llvm::SmallBitVector &getAliasesForRegister(SizeT) const = 0;
+
   void regAlloc(RegAllocKind Kind);
 
   virtual void
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 9b10eff..5edd00a 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -187,6 +187,8 @@
   Float32Registers[RegARM32::val] = isFP32;                                    \
   Float64Registers[RegARM32::val] = isFP64;                                    \
   VectorRegisters[RegARM32::val] = isVec128;                                   \
+  RegisterAliases[RegARM32::val].resize(RegARM32::Reg_NUM);                    \
+  RegisterAliases[RegARM32::val].set(RegARM32::val);                           \
   ScratchRegs[RegARM32::val] = scratch;
   REGARM32_TABLE;
 #undef X
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 0597510..8e50b22 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -68,6 +68,9 @@
   const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
     return TypeToRegisterSet[Ty];
   }
+  const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+    return RegisterAliases[Reg];
+  }
   bool hasFramePointer() const override { return UsesFramePointer; }
   SizeT getFrameOrStackReg() const override {
     return UsesFramePointer ? RegARM32::Reg_fp : RegARM32::Reg_sp;
@@ -434,7 +437,9 @@
   bool NeedsStackAlignment = false;
   bool MaybeLeafFunc = true;
   size_t SpillAreaSizeBytes = 0;
+  // TODO(jpp): std::array instead of array.
   llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
+  llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM];
   llvm::SmallBitVector ScratchRegs;
   llvm::SmallBitVector RegsUsed;
   VarList PhysicalRegisters[IceType_NUM];
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 8f434b5..00a294a 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -56,6 +56,8 @@
   IntegerRegisters[RegMIPS32::val] = isInt;                                    \
   FloatRegisters[RegMIPS32::val] = isFP;                                       \
   VectorRegisters[RegMIPS32::val] = isFP;                                      \
+  RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM);                  \
+  RegisterAliases[RegMIPS32::val].set(RegMIPS32::val);                         \
   ScratchRegs[RegMIPS32::val] = scratch;
   REGMIPS32_TABLE;
 #undef X
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 4fe1995..52c09cf 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -44,6 +44,9 @@
   const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
     return TypeToRegisterSet[Ty];
   }
+  const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+    return RegisterAliases[Reg];
+  }
   bool hasFramePointer() const override { return UsesFramePointer; }
   SizeT getFrameOrStackReg() const override {
     return UsesFramePointer ? RegMIPS32::Reg_FP : RegMIPS32::Reg_SP;
@@ -128,6 +131,7 @@
   bool UsesFramePointer = false;
   bool NeedsStackAlignment = false;
   llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
+  llvm::SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
   llvm::SmallBitVector ScratchRegs;
   llvm::SmallBitVector RegsUsed;
   VarList PhysicalRegisters[IceType_NUM];
diff --git a/src/IceTargetLoweringX8632Traits.h b/src/IceTargetLoweringX8632Traits.h
index 3bfd404..fc324d4 100644
--- a/src/IceTargetLoweringX8632Traits.h
+++ b/src/IceTargetLoweringX8632Traits.h
@@ -25,6 +25,8 @@
 #include "IceTargetLoweringX8632.def"
 #include "IceTargetLowering.h"
 
+#include <array>
+
 namespace Ice {
 
 class TargetX8632;
@@ -312,20 +314,43 @@
     }
   }
 
-  static void initRegisterSet(llvm::SmallBitVector *IntegerRegisters,
-                              llvm::SmallBitVector *IntegerRegistersI8,
-                              llvm::SmallBitVector *FloatRegisters,
-                              llvm::SmallBitVector *VectorRegisters,
-                              llvm::SmallBitVector *ScratchRegs) {
+  static void initRegisterSet(
+      std::array<llvm::SmallBitVector, IceType_NUM> *TypeToRegisterSet,
+      std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases,
+      llvm::SmallBitVector *ScratchRegs) {
+    llvm::SmallBitVector IntegerRegisters(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
+    ScratchRegs->resize(RegisterSet::Reg_NUM);
 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
           frameptr, isI8, isInt, isFP)                                         \
-  (*IntegerRegisters)[RegisterSet::val] = isInt;                               \
-  (*IntegerRegistersI8)[RegisterSet::val] = isI8;                              \
-  (*FloatRegisters)[RegisterSet::val] = isFP;                                  \
-  (*VectorRegisters)[RegisterSet::val] = isFP;                                 \
+  (IntegerRegisters)[RegisterSet::val] = isInt;                                \
+  (IntegerRegistersI8)[RegisterSet::val] = isI8;                               \
+  (FloatRegisters)[RegisterSet::val] = isFP;                                   \
+  (VectorRegisters)[RegisterSet::val] = isFP;                                  \
+  (*RegisterAliases)[RegisterSet::val].resize(RegisterSet::Reg_NUM);           \
+  (*RegisterAliases)[RegisterSet::val].set(RegisterSet::val);                  \
   (*ScratchRegs)[RegisterSet::val] = scratch;
     REGX8632_TABLE;
 #undef X
+
+    (*TypeToRegisterSet)[IceType_void] = InvalidRegisters;
+    (*TypeToRegisterSet)[IceType_i1] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[IceType_i8] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[IceType_i16] = IntegerRegisters;
+    (*TypeToRegisterSet)[IceType_i32] = IntegerRegisters;
+    (*TypeToRegisterSet)[IceType_i64] = IntegerRegisters;
+    (*TypeToRegisterSet)[IceType_f32] = FloatRegisters;
+    (*TypeToRegisterSet)[IceType_f64] = FloatRegisters;
+    (*TypeToRegisterSet)[IceType_v4i1] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v8i1] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v16i1] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v16i8] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v8i16] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v4i32] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v4f32] = VectorRegisters;
   }
 
   static llvm::SmallBitVector
diff --git a/src/IceTargetLoweringX8664Traits.h b/src/IceTargetLoweringX8664Traits.h
index a84dbc4..2caaeb5 100644
--- a/src/IceTargetLoweringX8664Traits.h
+++ b/src/IceTargetLoweringX8664Traits.h
@@ -25,6 +25,8 @@
 #include "IceTargetLowering.h"
 #include "IceTargetLoweringX8664.def"
 
+#include <array>
+
 namespace Ice {
 
 class TargetX8664;
@@ -325,20 +327,44 @@
     }
   }
 
-  static void initRegisterSet(llvm::SmallBitVector *IntegerRegisters,
-                              llvm::SmallBitVector *IntegerRegistersI8,
-                              llvm::SmallBitVector *FloatRegisters,
-                              llvm::SmallBitVector *VectorRegisters,
-                              llvm::SmallBitVector *ScratchRegs) {
+  static void initRegisterSet(
+      std::array<llvm::SmallBitVector, IceType_NUM> *TypeToRegisterSet,
+      std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases,
+      llvm::SmallBitVector *ScratchRegs) {
+    llvm::SmallBitVector IntegerRegisters(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
+    llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
+    ScratchRegs->resize(RegisterSet::Reg_NUM);
+
 #define X(val, encode, name64, name32, name16, name8, scratch, preserved,      \
           stackptr, frameptr, isInt, isFP)                                     \
-  (*IntegerRegisters)[RegisterSet::val] = isInt;                               \
-  (*IntegerRegistersI8)[RegisterSet::val] = isInt;                             \
-  (*FloatRegisters)[RegisterSet::val] = isFP;                                  \
-  (*VectorRegisters)[RegisterSet::val] = isFP;                                 \
+  (IntegerRegisters)[RegisterSet::val] = isInt;                                \
+  (IntegerRegistersI8)[RegisterSet::val] = isInt;                              \
+  (FloatRegisters)[RegisterSet::val] = isFP;                                   \
+  (VectorRegisters)[RegisterSet::val] = isFP;                                  \
+  (*RegisterAliases)[RegisterSet::val].resize(RegisterSet::Reg_NUM);           \
+  (*RegisterAliases)[RegisterSet::val].set(RegisterSet::val);                  \
   (*ScratchRegs)[RegisterSet::val] = scratch;
     REGX8664_TABLE;
 #undef X
+
+    (*TypeToRegisterSet)[IceType_void] = InvalidRegisters;
+    (*TypeToRegisterSet)[IceType_i1] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[IceType_i8] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[IceType_i16] = IntegerRegisters;
+    (*TypeToRegisterSet)[IceType_i32] = IntegerRegisters;
+    (*TypeToRegisterSet)[IceType_i64] = IntegerRegisters;
+    (*TypeToRegisterSet)[IceType_f32] = FloatRegisters;
+    (*TypeToRegisterSet)[IceType_f64] = FloatRegisters;
+    (*TypeToRegisterSet)[IceType_v4i1] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v8i1] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v16i1] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v16i8] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v8i16] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v4i32] = VectorRegisters;
+    (*TypeToRegisterSet)[IceType_v4f32] = VectorRegisters;
   }
 
   static llvm::SmallBitVector
diff --git a/src/IceTargetLoweringX86Base.h b/src/IceTargetLoweringX86Base.h
index 8c0f298..90effed 100644
--- a/src/IceTargetLoweringX86Base.h
+++ b/src/IceTargetLoweringX86Base.h
@@ -23,6 +23,7 @@
 #include "IceTargetLowering.h"
 #include "IceUtils.h"
 
+#include <array>
 #include <type_traits>
 #include <utility>
 
@@ -75,6 +76,12 @@
   const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
     return TypeToRegisterSet[Ty];
   }
+
+  const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
+    assert(Reg < Traits::RegisterSet::Reg_NUM);
+    return RegisterAliases[Reg];
+  }
+
   bool hasFramePointer() const override { return IsEbpBasedFrame; }
   SizeT getFrameOrStackReg() const override {
     return IsEbpBasedFrame ? Traits::RegisterSet::Reg_ebp
@@ -680,10 +687,12 @@
   bool IsEbpBasedFrame = false;
   bool NeedsStackAlignment = false;
   size_t SpillAreaSizeBytes = 0;
-  llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
+  std::array<llvm::SmallBitVector, IceType_NUM> TypeToRegisterSet;
+  std::array<llvm::SmallBitVector, Traits::RegisterSet::Reg_NUM>
+      RegisterAliases;
   llvm::SmallBitVector ScratchRegs;
   llvm::SmallBitVector RegsUsed;
-  VarList PhysicalRegisters[IceType_NUM];
+  std::array<VarList, IceType_NUM> PhysicalRegisters;
 
   /// Randomize a given immediate operand
   Operand *randomizeOrPoolImmediate(Constant *Immediate,
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index c061b33..99a1aeb 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -281,31 +281,7 @@
   }
   // TODO: Don't initialize IntegerRegisters and friends every time. Instead,
   // initialize in some sort of static initializer for the class.
-  llvm::SmallBitVector IntegerRegisters(Traits::RegisterSet::Reg_NUM);
-  llvm::SmallBitVector IntegerRegistersI8(Traits::RegisterSet::Reg_NUM);
-  llvm::SmallBitVector FloatRegisters(Traits::RegisterSet::Reg_NUM);
-  llvm::SmallBitVector VectorRegisters(Traits::RegisterSet::Reg_NUM);
-  llvm::SmallBitVector InvalidRegisters(Traits::RegisterSet::Reg_NUM);
-  ScratchRegs.resize(Traits::RegisterSet::Reg_NUM);
-
-  Traits::initRegisterSet(&IntegerRegisters, &IntegerRegistersI8,
-                          &FloatRegisters, &VectorRegisters, &ScratchRegs);
-
-  TypeToRegisterSet[IceType_void] = InvalidRegisters;
-  TypeToRegisterSet[IceType_i1] = IntegerRegistersI8;
-  TypeToRegisterSet[IceType_i8] = IntegerRegistersI8;
-  TypeToRegisterSet[IceType_i16] = IntegerRegisters;
-  TypeToRegisterSet[IceType_i32] = IntegerRegisters;
-  TypeToRegisterSet[IceType_i64] = IntegerRegisters;
-  TypeToRegisterSet[IceType_f32] = FloatRegisters;
-  TypeToRegisterSet[IceType_f64] = FloatRegisters;
-  TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
-  TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
-  TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
-  TypeToRegisterSet[IceType_v16i8] = VectorRegisters;
-  TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
-  TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
-  TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
+  Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs);
 }
 
 template <class Machine> void TargetX86Base<Machine>::translateO2() {