Move remaining Subzero x86 traits to their corresponding class

Functionality related to registers was moved to the corresponding Reg
class, while lowering functionality was moved to the corresponding
Target class.

This change also specializes for X86_PASS_SCALAR_FP_IN_XMM: x86-32 uses
x87 registers for scalar floating-point arguments and return values,
while x86-64 always uses XMM registers.

The SizeOf class was eliminated by making use of the C++14
initializer_list<>::size() functionality.

Bug: b/192890685
Change-Id: Id74b11ec1a873b60fb900627edd7984f60b5c761
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/55868
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/third_party/subzero/src/IceAssemblerX8632.cpp b/third_party/subzero/src/IceAssemblerX8632.cpp
index 8b4b0e1..dc1a9c3 100644
--- a/third_party/subzero/src/IceAssemblerX8632.cpp
+++ b/third_party/subzero/src/IceAssemblerX8632.cpp
@@ -51,7 +51,7 @@
     }
   }
 
-  GPRRegister Base = Traits::getEncodedGPR(BaseRegNum);
+  GPRRegister Base = RegX8632::getEncodedGPR(BaseRegNum);
 
   if (Utils::IsInt(8, Offset)) {
     SetModRM(1, Base);
@@ -94,13 +94,13 @@
 
   // Now convert to the various possible forms.
   if (Mem->getBase() && Mem->getIndex()) {
-    SetBaseIndex(Traits::getEncodedGPR(Mem->getBase()->getRegNum()),
-                 Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+    SetBaseIndex(RegX8632::getEncodedGPR(Mem->getBase()->getRegNum()),
+                 RegX8632::getEncodedGPR(Mem->getIndex()->getRegNum()),
                  ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else if (Mem->getBase()) {
-    SetBase(Traits::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
+    SetBase(RegX8632::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
   } else if (Mem->getIndex()) {
-    SetIndex(Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+    SetIndex(RegX8632::getEncodedGPR(Mem->getIndex()->getRegNum()),
              ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else {
     SetAbsolute(Disp, Fixup);
@@ -111,7 +111,7 @@
   assert(!Split->getVar()->hasReg());
   const ::Ice::TargetLowering *Target = Func->getTarget();
   int32_t Offset = Split->getVar()->getStackOffset() + Split->getOffset();
-  SetBase(Traits::getEncodedGPR(Target->getFrameOrStackReg()), Offset,
+  SetBase(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset,
           AssemblerFixup::NoFixup);
 }
 
@@ -136,8 +136,8 @@
   }
 }
 
-typename AssemblerX8632::Label *
-AssemblerX8632::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
+AssemblerX8632::Label *AssemblerX8632::getOrCreateLabel(SizeT Number,
+                                                        LabelVector &Labels) {
   Label *L = nullptr;
   if (Number == Labels.size()) {
     L = new (this->allocate<Label>()) Label();
@@ -160,13 +160,12 @@
   return CfgNodeLabels[NodeNumber];
 }
 
-typename AssemblerX8632::Label *
+AssemblerX8632::Label *
 AssemblerX8632::getOrCreateCfgNodeLabel(SizeT NodeNumber) {
   return getOrCreateLabel(NodeNumber, CfgNodeLabels);
 }
 
-typename AssemblerX8632::Label *
-AssemblerX8632::getOrCreateLocalLabel(SizeT Number) {
+AssemblerX8632::Label *AssemblerX8632::getOrCreateLocalLabel(SizeT Number) {
   return getOrCreateLabel(Number, LocalLabels);
 }
 
@@ -3005,7 +3004,7 @@
   emitUint8(0x0B);
 
   // mov $111, ebx
-  constexpr GPRRegister dst = Traits::GPRRegister::Encoded_Reg_ebx;
+  constexpr GPRRegister dst = GPRRegister::Encoded_Reg_ebx;
   constexpr Type Ty = IceType_i32;
   emitUint8(0xB8 + gprEncoding(dst));
   emitImmediate(Ty, Immediate(111));
@@ -3019,7 +3018,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
 
   // mov $222, ebx
-  constexpr GPRRegister dst = Traits::GPRRegister::Encoded_Reg_ebx;
+  constexpr GPRRegister dst = GPRRegister::Encoded_Reg_ebx;
   constexpr Type Ty = IceType_i32;
   emitUint8(0xB8 + gprEncoding(dst));
   emitImmediate(Ty, Immediate(222));
diff --git a/third_party/subzero/src/IceAssemblerX8632.h b/third_party/subzero/src/IceAssemblerX8632.h
index 0d50706..a42c039 100644
--- a/third_party/subzero/src/IceAssemblerX8632.h
+++ b/third_party/subzero/src/IceAssemblerX8632.h
@@ -24,25 +24,26 @@
 #define SUBZERO_SRC_ICEASSEMBLERX8632_H
 
 #include "IceAssembler.h"
+#include "IceConditionCodesX86.h"
 #include "IceDefs.h"
 #include "IceOperand.h"
+#include "IceRegistersX8632.h"
 #include "IceTypes.h"
 #include "IceUtils.h"
 
-#include "IceTargetLoweringX8632Traits.h"
-
 namespace Ice {
 namespace X8632 {
 
-using Traits = TargetX8632Traits;
-using ByteRegister = typename Traits::ByteRegister;
 using BrCond = CondX86::BrCond;
 using CmppsCond = CondX86::CmppsCond;
-using GPRRegister = typename Traits::GPRRegister;
-using XmmRegister = typename Traits::XmmRegister;
+using RegisterSet = ::Ice::RegX8632;
+using GPRRegister = RegisterSet::GPRRegister;
+using ByteRegister = RegisterSet::ByteRegister;
+using XmmRegister = RegisterSet::XmmRegister;
 
 class X86OperandMem;
 class VariableSplit;
+class TargetX8632;
 
 constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
 constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
@@ -881,8 +882,7 @@
 
   static constexpr Type RexTypeIrrelevant = IceType_i32;
   static constexpr Type RexTypeForceRexW = IceType_i64;
-  static constexpr GPRRegister RexRegIrrelevant =
-      Traits::GPRRegister::Encoded_Reg_eax;
+  static constexpr GPRRegister RexRegIrrelevant = GPRRegister::Encoded_Reg_eax;
 
   inline void emitInt16(int16_t value);
   inline void emitInt32(int32_t value);
@@ -932,9 +932,8 @@
   void arith_int(Type Ty, const AsmAddress &address, const Immediate &imm);
 
   // gprEncoding returns Reg encoding for operand emission.
-  template <typename RegType, typename T = Traits>
-  typename T::GPRRegister gprEncoding(const RegType Reg) {
-    return static_cast<typename T::GPRRegister>(Reg);
+  template <typename RegType> GPRRegister gprEncoding(const RegType Reg) {
+    return static_cast<GPRRegister>(Reg);
   }
 };
 
diff --git a/third_party/subzero/src/IceAssemblerX8664.cpp b/third_party/subzero/src/IceAssemblerX8664.cpp
index 65b611b..3c49308 100644
--- a/third_party/subzero/src/IceAssemblerX8664.cpp
+++ b/third_party/subzero/src/IceAssemblerX8664.cpp
@@ -50,7 +50,7 @@
       BaseRegNum = Target->getFrameOrStackReg();
     }
   }
-  SetBase(Traits::getEncodedGPR(BaseRegNum), Offset, AssemblerFixup::NoFixup);
+  SetBase(RegX8664::getEncodedGPR(BaseRegNum), Offset, AssemblerFixup::NoFixup);
 }
 
 AsmAddress::AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
@@ -85,13 +85,13 @@
 
   // Now convert to the various possible forms.
   if (Mem->getBase() && Mem->getIndex()) {
-    SetBaseIndex(Traits::getEncodedGPR(Mem->getBase()->getRegNum()),
-                 Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+    SetBaseIndex(RegX8664::getEncodedGPR(Mem->getBase()->getRegNum()),
+                 RegX8664::getEncodedGPR(Mem->getIndex()->getRegNum()),
                  ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else if (Mem->getBase()) {
-    SetBase(Traits::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
+    SetBase(RegX8664::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
   } else if (Mem->getIndex()) {
-    SetIndex(Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+    SetIndex(RegX8664::getEncodedGPR(Mem->getIndex()->getRegNum()),
              ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else if (Fixup == nullptr) {
     SetAbsolute(Disp);
@@ -121,8 +121,8 @@
   }
 }
 
-typename AssemblerX8664::Label *
-AssemblerX8664::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
+AssemblerX8664::Label *AssemblerX8664::getOrCreateLabel(SizeT Number,
+                                                        LabelVector &Labels) {
   Label *L = nullptr;
   if (Number == Labels.size()) {
     L = new (this->allocate<Label>()) Label();
@@ -145,13 +145,12 @@
   return CfgNodeLabels[NodeNumber];
 }
 
-typename AssemblerX8664::Label *
+AssemblerX8664::Label *
 AssemblerX8664::getOrCreateCfgNodeLabel(SizeT NodeNumber) {
   return getOrCreateLabel(NodeNumber, CfgNodeLabels);
 }
 
-typename AssemblerX8664::Label *
-AssemblerX8664::getOrCreateLocalLabel(SizeT Number) {
+AssemblerX8664::Label *AssemblerX8664::getOrCreateLocalLabel(SizeT Number) {
   return getOrCreateLabel(Number, LocalLabels);
 }
 
@@ -3167,7 +3166,7 @@
   emitUint8(0x0B);
 
   // mov $111, ebx
-  constexpr GPRRegister dst = Traits::GPRRegister::Encoded_Reg_ebx;
+  constexpr GPRRegister dst = GPRRegister::Encoded_Reg_ebx;
   constexpr Type Ty = IceType_i32;
   emitRexB(Ty, dst);
   emitUint8(0xB8 + gprEncoding(dst));
@@ -3182,7 +3181,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
 
   // mov $222, ebx
-  constexpr GPRRegister dst = Traits::GPRRegister::Encoded_Reg_ebx;
+  constexpr GPRRegister dst = GPRRegister::Encoded_Reg_ebx;
   constexpr Type Ty = IceType_i32;
   emitRexB(Ty, dst);
   emitUint8(0xB8 + gprEncoding(dst));
diff --git a/third_party/subzero/src/IceAssemblerX8664.h b/third_party/subzero/src/IceAssemblerX8664.h
index ed2e519..656f07a 100644
--- a/third_party/subzero/src/IceAssemblerX8664.h
+++ b/third_party/subzero/src/IceAssemblerX8664.h
@@ -24,24 +24,25 @@
 #define SUBZERO_SRC_ICEASSEMBLERX8664_H
 
 #include "IceAssembler.h"
+#include "IceConditionCodesX86.h"
 #include "IceDefs.h"
 #include "IceOperand.h"
+#include "IceRegistersX8664.h"
 #include "IceTypes.h"
 #include "IceUtils.h"
 
-#include "IceTargetLoweringX8664Traits.h"
-
 namespace Ice {
 namespace X8664 {
 
-using Traits = TargetX8664Traits;
-using ByteRegister = typename Traits::ByteRegister;
 using BrCond = CondX86::BrCond;
 using CmppsCond = CondX86::CmppsCond;
-using GPRRegister = typename Traits::GPRRegister;
-using XmmRegister = typename Traits::XmmRegister;
+using RegisterSet = ::Ice::RegX8664;
+using GPRRegister = RegisterSet::GPRRegister;
+using ByteRegister = RegisterSet::ByteRegister;
+using XmmRegister = RegisterSet::XmmRegister;
 
 class X86OperandMem;
+class TargetX8664;
 
 constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32;
 constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32S;
@@ -370,7 +371,6 @@
 
   bool fixupIsPCRel(FixupKind Kind) const override {
     // Currently assuming this is the only PC-rel relocation type used.
-    // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
     return Kind == FK_PcRel;
   }
 
@@ -878,8 +878,7 @@
 
   static constexpr Type RexTypeIrrelevant = IceType_i32;
   static constexpr Type RexTypeForceRexW = IceType_i64;
-  static constexpr GPRRegister RexRegIrrelevant =
-      Traits::GPRRegister::Encoded_Reg_eax;
+  static constexpr GPRRegister RexRegIrrelevant = GPRRegister::Encoded_Reg_eax;
 
   inline void emitInt16(int16_t value);
   inline void emitInt32(int32_t value);
@@ -948,8 +947,8 @@
     //
     // The "local" uint32_t Encoded_Reg_ah is needed because RegType is an
     // enum that is not necessarily the same type of
-    // Traits::RegisterSet::Encoded_Reg_ah.
-    constexpr uint32_t Encoded_Reg_ah = Traits::RegisterSet::Encoded_Reg_ah;
+    // RegisterSet::Encoded_Reg_ah.
+    constexpr uint32_t Encoded_Reg_ah = RegisterSet::Encoded_Reg_ah;
     return IsGPR && (Reg & 0x04) != 0 && (Reg & 0x08) == 0 &&
            isByteSizedType(Ty) && (Reg != Encoded_Reg_ah);
   }
@@ -967,13 +966,11 @@
                           ? AsmOperand::RexW
                           : AsmOperand::RexNone;
     const uint8_t R = (Reg & 0x08) ? AsmOperand::RexR : AsmOperand::RexNone;
-    const uint8_t X = (Addr != nullptr)
-                          ? (typename AsmOperand::RexBits)Addr->rexX()
-                          : AsmOperand::RexNone;
-    const uint8_t B = (Addr != nullptr)
-                          ? (typename AsmOperand::RexBits)Addr->rexB()
-                      : (Rm & 0x08) ? AsmOperand::RexB
-                                    : AsmOperand::RexNone;
+    const uint8_t X = (Addr != nullptr) ? (AsmOperand::RexBits)Addr->rexX()
+                                        : AsmOperand::RexNone;
+    const uint8_t B = (Addr != nullptr) ? (AsmOperand::RexBits)Addr->rexB()
+                      : (Rm & 0x08)     ? AsmOperand::RexB
+                                        : AsmOperand::RexNone;
     const uint8_t Prefix = W | R | X | B;
     if (Prefix != AsmOperand::RexNone) {
       emitUint8(Prefix);
diff --git a/third_party/subzero/src/IceInstX8632.cpp b/third_party/subzero/src/IceInstX8632.cpp
index e623ae1..fe87eee 100644
--- a/third_party/subzero/src/IceInstX8632.cpp
+++ b/third_party/subzero/src/IceInstX8632.cpp
@@ -8,8 +8,7 @@
 //===----------------------------------------------------------------------===//
 ///
 /// \file
-/// \brief Defines X8632 specific data related to X8632 Instructions and
-/// Instruction traits.
+/// \brief Defines X8632 specific data related to X8632 Instructions.
 ///
 //===----------------------------------------------------------------------===//
 
@@ -41,6 +40,7 @@
 };
 
 struct TypeAttributesType {
+  const Type InVectorElementType;
   const char *const CvtString;      // i (integer), s (single FP), d (double FP)
   const char *const SdSsString;     // ss, sd, or <blank>
   const char *const PdPsString;     // ps, pd, or <blank>
@@ -66,7 +66,7 @@
 
 constexpr TypeAttributesType TypeAttributes[] = {
 #define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld)    \
-  {cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld},
+  {IceType_##elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld},
     ICETYPEX86_TABLE
 #undef X
 };
@@ -109,7 +109,15 @@
   }
 }
 
-typename Cond::BrCond InstX86Base::getOppositeCondition(BrCond Cond) {
+/// Return the type which the elements of the vector have in the X86
+/// representation of the vector.
+Type InstX86Base::getInVectorElementType(Type Ty) {
+  assert(isVectorType(Ty));
+  assert(static_cast<size_t>(Ty) < std::size(TypeAttributes));
+  return TypeAttributes[Ty].InVectorElementType;
+}
+
+Cond::BrCond InstX86Base::getOppositeCondition(BrCond Cond) {
   return InstBrAttributes[Cond].Opposite;
 }
 
@@ -251,7 +259,7 @@
                           llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
   constexpr uint16_t Encoded_rAX = 0;
   (void)Encoded_rAX;
-  assert(Traits::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
+  assert(RegX8632::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
   this->addSource(DestOrAddr);
   this->addSource(Eax);
   this->addSource(Desired);
@@ -396,7 +404,7 @@
   if (!BuildDefs::dump())
     return;
   Ostream &Str = Func->getContext()->getStrDump();
-  Str << "[" << Traits::TargetName << "] ";
+  Str << "[X8632] ";
   Inst::dump(Func);
 }
 
@@ -535,7 +543,7 @@
   Operand *Target = getJmpTarget();
   if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
     if (Var->hasReg()) {
-      Asm->jmp(Traits::getEncodedGPR(Var->getRegNum()));
+      Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum()));
     } else {
       // The jmp instruction with a memory operand should be possible to
       // encode, but it isn't a valid sandboxed instruction, and there
@@ -594,7 +602,7 @@
   auto *Target = InstX86Base::getTarget(Func);
   if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
     if (Var->hasReg()) {
-      Asm->call(Traits::getEncodedGPR(Var->getRegNum()));
+      Asm->call(RegX8632::getEncodedGPR(Var->getRegNum()));
     } else {
       Asm->call(AsmAddress(Var, Target));
     }
@@ -650,7 +658,7 @@
   if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
     if (Var->hasReg()) {
       // We cheat a little and use GPRRegister even for byte operations.
-      GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
+      GPRRegister VarReg = RegX8632::getEncodedGPR(Var->getRegNum());
       (Asm->*(Emitter.Reg))(Ty, VarReg);
     } else {
       AsmAddress StackAddr(AsmAddress(Var, Target));
@@ -671,13 +679,13 @@
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(Var->hasReg());
   // We cheat a little and use GPRRegister even for byte operations.
-  GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
-                                    : Traits::getEncodedGPR(Var->getRegNum());
+  GPRRegister VarReg = VarCanBeByte ? RegX8632::getEncodedGPR(Var->getRegNum())
+                                    : RegX8632::getEncodedGPR(Var->getRegNum());
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
       GPRRegister SrcReg = SrcCanBeByte
-                               ? Traits::getEncodedGPR(SrcVar->getRegNum())
-                               : Traits::getEncodedGPR(SrcVar->getRegNum());
+                               ? RegX8632::getEncodedGPR(SrcVar->getRegNum())
+                               : RegX8632::getEncodedGPR(SrcVar->getRegNum());
       (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
     } else {
       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
@@ -708,7 +716,7 @@
   // Src can only be Reg or AssemblerImmediate.
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     assert(SrcVar->hasReg());
-    GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
+    GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar->getRegNum());
     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
@@ -749,11 +757,11 @@
   // extend this to check Dest if we decide to use that form.
   assert(Var->hasReg());
   // We cheat a little and use GPRRegister even for byte operations.
-  GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
+  GPRRegister VarReg = RegX8632::getEncodedGPR(Var->getRegNum());
   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     assert(SrcVar->hasReg());
-    GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
+    GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar->getRegNum());
     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
@@ -768,11 +776,11 @@
   Assembler *Asm = Func->getAssembler<Assembler>();
   // Dest can be reg or mem, but we only use the reg variant.
   assert(Dest->hasReg());
-  GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
+  GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum());
   // SrcVar1 must be reg.
   const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
   assert(SrcVar1->hasReg());
-  GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar1->getRegNum());
+  GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum());
   Type Ty = SrcVar1->getType();
   // Src2 can be the implicit CL register or an immediate.
   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
@@ -789,10 +797,10 @@
   auto *Target = InstX86Base::getTarget(Func);
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(Var->hasReg());
-  XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
+  XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
-      XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+      XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
     } else {
       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
@@ -813,10 +821,10 @@
   auto *Target = InstX86Base::getTarget(Func);
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(Var->hasReg());
-  XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
+  XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
-      XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+      XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
     } else {
       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
@@ -892,11 +900,11 @@
   auto *Target = InstX86Base::getTarget(Func);
   Assembler *Asm = Func->getAssembler<Assembler>();
   if (Dest->hasReg()) {
-    XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
+    XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
     if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
       if (SrcVar->hasReg()) {
         (Asm->*(Emitter.XmmXmm))(DestReg,
-                                 Traits::getEncodedXmm(SrcVar->getRegNum()));
+                                 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
       } else {
         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
@@ -913,7 +921,7 @@
     const auto *SrcVar = llvm::cast<Variable>(Src);
     assert(SrcVar->hasReg());
     (Asm->*(Emitter.AddrXmm))(StackAddr,
-                              Traits::getEncodedXmm(SrcVar->getRegNum()));
+                              RegX8632::getEncodedXmm(SrcVar->getRegNum()));
   }
 }
 
@@ -964,8 +972,8 @@
   assert(isVectorType(SrcTy));
   assert(isScalarIntegerType(DestTy));
   assert(typeWidthInBytes(DestTy) <= 4);
-  XmmRegister SrcReg = Traits::getEncodedXmm(Src->getRegNum());
-  GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
+  XmmRegister SrcReg = RegX8632::getEncodedXmm(Src->getRegNum());
+  GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum());
   Asm->movmsk(SrcTy, DestReg, SrcReg);
 }
 
@@ -1145,9 +1153,9 @@
   assert(llvm::isa<Constant>(this->getSrc(1)));
   static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
       &Assembler::imul, &Assembler::imul};
-  emitIASThreeOpImmOps<GPRRegister, GPRRegister, Traits::getEncodedGPR,
-                       Traits::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
-                                              this->getSrc(1), Emitter);
+  emitIASThreeOpImmOps<GPRRegister, GPRRegister, RegX8632::getEncodedGPR,
+                       RegX8632::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
+                                                this->getSrc(1), Emitter);
 }
 
 void InstX86Insertps::emitIAS(const Cfg *Func) const {
@@ -1158,9 +1166,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::insertps, &Assembler::insertps};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
-                                              this->getSrc(2), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
+                       RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
+                                                this->getSrc(2), Emitter);
 }
 
 void InstX86Cbwdq::emit(const Cfg *Func) const {
@@ -1367,17 +1375,17 @@
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
       Asm->cmov(SrcTy, Condition,
-                Traits::getEncodedGPR(this->getDest()->getRegNum()),
-                Traits::getEncodedGPR(SrcVar->getRegNum()));
+                RegX8632::getEncodedGPR(this->getDest()->getRegNum()),
+                RegX8632::getEncodedGPR(SrcVar->getRegNum()));
     } else {
       Asm->cmov(SrcTy, Condition,
-                Traits::getEncodedGPR(this->getDest()->getRegNum()),
+                RegX8632::getEncodedGPR(this->getDest()->getRegNum()),
                 AsmAddress(SrcVar, Target));
     }
   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
     Asm->cmov(SrcTy, Condition,
-              Traits::getEncodedGPR(this->getDest()->getRegNum()),
+              RegX8632::getEncodedGPR(this->getDest()->getRegNum()),
               AsmAddress(Mem, Asm, Target));
   } else {
     llvm_unreachable("Unexpected operand type");
@@ -1422,12 +1430,12 @@
   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
   if (SrcVar->hasReg()) {
     Asm->cmpps(this->getDest()->getType(),
-               Traits::getEncodedXmm(this->getDest()->getRegNum()),
-               Traits::getEncodedXmm(SrcVar->getRegNum()), Condition);
+               RegX8632::getEncodedXmm(this->getDest()->getRegNum()),
+               RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
   } else {
     AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
     Asm->cmpps(this->getDest()->getType(),
-               Traits::getEncodedXmm(this->getDest()->getRegNum()),
+               RegX8632::getEncodedXmm(this->getDest()->getRegNum()),
                SrcStackAddr, Condition);
   }
 }
@@ -1471,7 +1479,7 @@
   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
   const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
   assert(VarReg->hasReg());
-  const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
+  const GPRRegister Reg = RegX8632::getEncodedGPR(VarReg->getRegNum());
   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
 }
 
@@ -1550,9 +1558,9 @@
     assert(isScalarFloatingType(DestTy));
     static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
         &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
-    emitIASCastRegOp<XmmRegister, GPRRegister, Traits::getEncodedXmm,
-                     Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
-                                            Emitter);
+    emitIASCastRegOp<XmmRegister, GPRRegister, RegX8632::getEncodedXmm,
+                     RegX8632::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
+                                              Emitter);
     return;
   }
   case Tss2si: {
@@ -1561,9 +1569,9 @@
     assert(typeWidthInBytes(DestTy) <= 4);
     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
         &Assembler::cvttss2si, &Assembler::cvttss2si};
-    emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
-                     Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
-                                            Emitter);
+    emitIASCastRegOp<GPRRegister, XmmRegister, RegX8632::getEncodedGPR,
+                     RegX8632::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
+                                              Emitter);
     return;
   }
   case Ss2si: {
@@ -1572,9 +1580,9 @@
     assert(typeWidthInBytes(DestTy) <= 4);
     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
         &Assembler::cvtss2si, &Assembler::cvtss2si};
-    emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
-                     Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
-                                            Emitter);
+    emitIASCastRegOp<GPRRegister, XmmRegister, RegX8632::getEncodedGPR,
+                     RegX8632::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
+                                              Emitter);
     return;
   }
   case Float2float: {
@@ -1647,9 +1655,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::round, &Assembler::round};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
-                                              this->getSrc(1), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
+                       RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
+                                                this->getSrc(1), Emitter);
 }
 
 void InstX86Icmp::emit(const Cfg *Func) const {
@@ -1850,7 +1858,7 @@
     // Src must be a register, since Dest is a Mem operand of some kind.
     const auto *SrcVar = llvm::cast<Variable>(Src);
     assert(SrcVar->hasReg());
-    XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+    XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
     Assembler *Asm = Func->getAssembler<Assembler>();
     auto *Target = InstX86Base::getTarget(Func);
     if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
@@ -1903,7 +1911,7 @@
   assert(SrcVar->hasReg());
   auto *Target = InstX86Base::getTarget(Func);
   Asm->movups(AsmAddress(DestMem, Asm, Target),
-              Traits::getEncodedXmm(SrcVar->getRegNum()));
+              RegX8632::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86StoreP::dump(const Cfg *Func) const {
@@ -1940,7 +1948,7 @@
   assert(SrcVar->hasReg());
   auto *Target = InstX86Base::getTarget(Func);
   Asm->movq(AsmAddress(DestMem, Asm, Target),
-            Traits::getEncodedXmm(SrcVar->getRegNum()));
+            RegX8632::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86StoreQ::dump(const Cfg *Func) const {
@@ -1977,7 +1985,7 @@
   assert(SrcVar->hasReg());
   auto *Target = InstX86Base::getTarget(Func);
   Asm->movd(SrcVar->getType(), AsmAddress(DestMem, Asm, Target),
-            Traits::getEncodedXmm(SrcVar->getRegNum()));
+            RegX8632::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86StoreD::dump(const Cfg *Func) const {
@@ -2073,7 +2081,7 @@
   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     RegNumT NewRegNum;
     if (SrcVar->hasReg())
-      NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
+      NewRegNum = RegX8632::getGprForType(DestTy, SrcVar->getRegNum());
     if (SrcTy != DestTy)
       NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
   }
@@ -2131,14 +2139,15 @@
       const auto *SrcVar = llvm::cast<Variable>(Src);
       assert(SrcVar->hasReg());
       Assembler *Asm = Func->getAssembler<Assembler>();
-      Asm->movss(SrcTy, StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
+      Asm->movss(SrcTy, StackAddr,
+                 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
       return;
     } else if (isVectorType(SrcTy)) {
       // Src must be a register
       const auto *SrcVar = llvm::cast<Variable>(Src);
       assert(SrcVar->hasReg());
       Assembler *Asm = Func->getAssembler<Assembler>();
-      Asm->movups(StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
+      Asm->movups(StackAddr, RegX8632::getEncodedXmm(SrcVar->getRegNum()));
     } else {
       // Src can be a register or immediate.
       assert(isScalarIntegerType(SrcTy));
@@ -2186,10 +2195,10 @@
               typeWidthInBytes(SrcVar->getType()) ==
                   typeWidthInBytes(Dest->getType())));
       assert(Dest->hasReg());
-      XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
+      XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
       if (SrcVar->hasReg()) {
         Asm->movd(SrcVar->getType(), DestReg,
-                  Traits::getEncodedGPR(SrcVar->getRegNum()));
+                  RegX8632::getEncodedGPR(SrcVar->getRegNum()));
       } else {
         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
         Asm->movd(SrcVar->getType(), DestReg, StackAddr);
@@ -2201,9 +2210,9 @@
                   typeWidthInBytes(Dest->getType())));
       assert(SrcVar->hasReg());
       assert(Dest->getType() == IceType_i32);
-      XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+      XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
       if (Dest->hasReg()) {
-        Asm->movd(Dest->getType(), Traits::getEncodedGPR(Dest->getRegNum()),
+        Asm->movd(Dest->getType(), RegX8632::getEncodedGPR(Dest->getRegNum()),
                   SrcReg);
       } else {
         AsmAddress StackAddr(AsmAddress(Dest, Target));
@@ -2212,7 +2221,7 @@
     }
   } else {
     assert(Dest->hasReg());
-    XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
+    XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
     auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
     Asm->movd(Mem->getType(), DestReg, AsmAddress(Mem, Asm, Target));
   }
@@ -2279,8 +2288,8 @@
   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
   assert(Dest->hasReg() && SrcVar->hasReg());
   Assembler *Asm = Func->getAssembler<Assembler>();
-  Asm->movss(IceType_f32, Traits::getEncodedXmm(Dest->getRegNum()),
-             Traits::getEncodedXmm(SrcVar->getRegNum()));
+  Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()),
+             RegX8632::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86Movsx::emitIAS(const Cfg *Func) const {
@@ -2376,7 +2385,7 @@
       // stack slot.  Function prolog emission guarantees that there is
       // sufficient space to do this.
       AsmAddress StackSlot = AsmAddress(RegisterSet::Encoded_Reg_esp, 0);
-      Asm->movss(Ty, StackSlot, Traits::getEncodedXmm(Var->getRegNum()));
+      Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum()));
       Asm->fld(Ty, StackSlot);
     } else {
       AsmAddress StackAddr(AsmAddress(Var, Target));
@@ -2460,7 +2469,7 @@
     // st(0) there, and loading it into the xmm register.
     AsmAddress StackSlot = AsmAddress(RegisterSet::Encoded_Reg_esp, 0);
     Asm->fstp(Ty, StackSlot);
-    Asm->movss(Ty, Traits::getEncodedXmm(Dest->getRegNum()), StackSlot);
+    Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot);
   }
 }
 
@@ -2496,7 +2505,7 @@
   assert(this->getSrcSize() == 2);
   // pextrb and pextrd are SSE4.1 instructions.
   const Variable *Dest = this->getDest();
-  Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType());
+  Type DispatchTy = getInVectorElementType(this->getSrc(0)->getType());
   // pextrw must take a register dest. There is an SSE4.1 version that takes a
   // memory dest, but we aren't using it. For uniformity, just restrict them
   // all to have a register dest for now.
@@ -2505,8 +2514,8 @@
   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
   static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
       &Assembler::pextr, nullptr};
-  emitIASThreeOpImmOps<GPRRegister, XmmRegister, Traits::getEncodedGPR,
-                       Traits::getEncodedXmm>(
+  emitIASThreeOpImmOps<GPRRegister, XmmRegister, RegX8632::getEncodedGPR,
+                       RegX8632::getEncodedXmm>(
       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
 }
 
@@ -2523,7 +2532,7 @@
   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
     // If src1 is a register, it should always be r32.
     if (Src1Var->hasReg()) {
-      const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
+      const auto NewRegNum = RegX8632::getBaseReg(Src1Var->getRegNum());
       const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
       NewSrc->emit(Func);
     } else {
@@ -2550,18 +2559,18 @@
     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
       if (Src0Var->hasReg()) {
         const auto RegNum = Src0Var->getRegNum();
-        const auto BaseRegNum = Traits::getBaseReg(RegNum);
+        const auto BaseRegNum = RegX8632::getBaseReg(RegNum);
         (void)BaseRegNum;
-        assert(Traits::getEncodedGPR(RegNum) ==
-               Traits::getEncodedGPR(BaseRegNum));
+        assert(RegX8632::getEncodedGPR(RegNum) ==
+               RegX8632::getEncodedGPR(BaseRegNum));
       }
     }
   }
   static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
       &Assembler::pinsr, &Assembler::pinsr};
-  emitIASThreeOpImmOps<XmmRegister, GPRRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedGPR>(Func, DispatchTy, this->getDest(),
-                                              Src0, this->getSrc(2), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, GPRRegister, RegX8632::getEncodedXmm,
+                       RegX8632::getEncodedGPR>(
+      Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
 }
 
 void InstX86Pshufd::emitIAS(const Cfg *Func) const {
@@ -2570,9 +2579,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::pshufd, &Assembler::pshufd};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
-                                              this->getSrc(1), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
+                       RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
+                                                this->getSrc(1), Emitter);
 }
 
 void InstX86Shufps::emitIAS(const Cfg *Func) const {
@@ -2582,9 +2591,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::shufps, &Assembler::shufps};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
-                                              this->getSrc(2), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
+                       RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
+                                                this->getSrc(2), Emitter);
 }
 
 void InstX86Pop::emit(const Cfg *Func) const {
@@ -2601,7 +2610,7 @@
   assert(this->getSrcSize() == 0);
   Assembler *Asm = Func->getAssembler<Assembler>();
   if (this->getDest()->hasReg()) {
-    Asm->popl(Traits::getEncodedGPR(this->getDest()->getRegNum()));
+    Asm->popl(RegX8632::getEncodedGPR(this->getDest()->getRegNum()));
   } else {
     auto *Target = InstX86Base::getTarget(Func);
     Asm->popl(AsmAddress(this->getDest(), Target));
@@ -2635,7 +2644,7 @@
   const Operand *Src = this->getSrc(0);
 
   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
-    Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
+    Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum()));
   } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
     Asm->pushl(AssemblerImmediate(Const32->getValue()));
   } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
@@ -2694,7 +2703,7 @@
   auto *Target = InstX86Base::getTarget(Func);
   if (this->getDest()->hasReg())
     Asm->setcc(Condition,
-               Traits::getEncodedByteReg(this->getDest()->getRegNum()));
+               RegX8632::getEncodedByteReg(this->getDest()->getRegNum()));
   else
     Asm->setcc(Condition, AsmAddress(this->getDest(), Target));
   return;
@@ -2734,7 +2743,7 @@
   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
   const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
   assert(VarReg->hasReg());
-  const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
+  const GPRRegister Reg = RegX8632::getEncodedGPR(VarReg->getRegNum());
   Asm->xadd(Ty, Addr, Reg, this->Locked);
 }
 
@@ -2768,11 +2777,11 @@
   Type Ty = this->getSrc(0)->getType();
   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
   assert(VarReg1->hasReg());
-  const GPRRegister Reg1 = Traits::getEncodedGPR(VarReg1->getRegNum());
+  const GPRRegister Reg1 = RegX8632::getEncodedGPR(VarReg1->getRegNum());
 
   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
     assert(VarReg0->hasReg());
-    const GPRRegister Reg0 = Traits::getEncodedGPR(VarReg0->getRegNum());
+    const GPRRegister Reg0 = RegX8632::getEncodedGPR(VarReg0->getRegNum());
     Asm->xchg(Ty, Reg0, Reg1);
     return;
   }
diff --git a/third_party/subzero/src/IceInstX8632.h b/third_party/subzero/src/IceInstX8632.h
index b0d2c33..7bad651 100644
--- a/third_party/subzero/src/IceInstX8632.h
+++ b/third_party/subzero/src/IceInstX8632.h
@@ -11,16 +11,11 @@
 /// \brief This file defines the InstX86Base template class, as well as the
 /// generic X86 Instruction class hierarchy.
 ///
-/// Only X86 instructions common across all/most X86 targets should be defined
-/// here, with target-specific instructions declared in the target's traits.
-///
 //===----------------------------------------------------------------------===//
 
 #ifndef SUBZERO_SRC_ICEINSTX8632_H
 #define SUBZERO_SRC_ICEINSTX8632_H
 
-#include "IceTargetLoweringX8632Traits.h"
-
 #include "IceAssemblerX8632.h"
 #include "IceDefs.h"
 #include "IceInst.h"
@@ -30,14 +25,14 @@
 namespace Ice {
 namespace X8632 {
 
-using Traits = TargetX8632Traits;
 using Assembler = AssemblerX8632;
 using AssemblerImmediate = Assembler::Immediate;
 using TargetLowering = TargetX8632;
 
-using GPRRegister = typename Traits::RegisterSet::GPRRegister;
-using RegisterSet = typename Traits::RegisterSet;
-using XmmRegister = typename Traits::RegisterSet::XmmRegister;
+using RegisterSet = ::Ice::RegX8632;
+using GPRRegister = RegisterSet::GPRRegister;
+using ByteRegister = RegisterSet::ByteRegister;
+using XmmRegister = RegisterSet::XmmRegister;
 
 using Cond = CondX86;
 using BrCond = Cond::BrCond;
@@ -325,6 +320,7 @@
   static const char *getWidthString(Type Ty);
   static const char *getFldString(Type Ty);
   static const char *getSseSuffixString(Type DestTy, SseSuffix Suffix);
+  static Type getInVectorElementType(Type Ty);
   static BrCond getOppositeCondition(BrCond Cond);
   void dump(const Cfg *Func) const override;
 
@@ -1139,8 +1135,9 @@
         //                    is handled by Inst86Zext.
         const auto SrcReg = SrcVar->getRegNum();
         const auto DestReg = this->Dest->getRegNum();
-        return (Traits::getEncoding(SrcReg) == Traits::getEncoding(DestReg)) &&
-               (Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg));
+        return (RegX8632::getEncoding(SrcReg) ==
+                RegX8632::getEncoding(DestReg)) &&
+               (RegX8632::getBaseReg(SrcReg) == RegX8632::getBaseReg(DestReg));
       }
     }
     return checkForRedundantAssign(this->getDest(), this->getSrc(0));
@@ -2766,10 +2763,10 @@
   InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem);
 };
 
-/// This is essentially a vector "mov" instruction with an typename
-/// X86OperandMem operand instead of Variable as the destination. It's
-/// important for liveness that there is no Dest operand. The source must be
-/// an Xmm register, since Dest is mem.
+/// This is essentially a vector "mov" instruction with an X86OperandMem operand
+/// instead of Variable as the destination. It's important for liveness that
+/// there is no Dest operand. The source must be an Xmm register, since Dest is
+/// mem.
 class InstX86StoreP final : public InstX86Base {
   InstX86StoreP() = delete;
   InstX86StoreP(const InstX86StoreP &) = delete;
@@ -3160,10 +3157,6 @@
                             InstX86Base::SseSuffix::Pack>(Func, Dest, Source) {}
 };
 
-/// struct Insts is a template that can be used to instantiate all the X86
-/// instructions for a target with a simple
-///
-/// using Insts = ::Ice::X8632::Insts<TraitsType>;
 struct Insts {
   using FakeRMW = InstX86FakeRMW;
   using Label = InstX86Label;
diff --git a/third_party/subzero/src/IceInstX8664.cpp b/third_party/subzero/src/IceInstX8664.cpp
index d5e0f39..9d655a1 100644
--- a/third_party/subzero/src/IceInstX8664.cpp
+++ b/third_party/subzero/src/IceInstX8664.cpp
@@ -8,8 +8,7 @@
 //===----------------------------------------------------------------------===//
 ///
 /// \file
-/// \brief This file defines X8664 specific data related to X8664 Instructions
-/// and Instruction traits.
+/// \brief This file defines X8664 specific data related to X8664 Instructions.
 ///
 //===----------------------------------------------------------------------===//
 
@@ -41,6 +40,7 @@
 };
 
 struct TypeAttributesType {
+  const Type InVectorElementType;
   const char *const CvtString;      // i (integer), s (single FP), d (double FP)
   const char *const SdSsString;     // ss, sd, or <blank>
   const char *const PdPsString;     // ps, pd, or <blank>
@@ -66,7 +66,7 @@
 
 constexpr TypeAttributesType TypeAttributes[] = {
 #define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld)    \
-  {cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld},
+  {IceType_##elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld},
     ICETYPEX86_TABLE
 #undef X
 };
@@ -97,7 +97,15 @@
   }
 }
 
-typename Cond::BrCond InstX86Base::getOppositeCondition(BrCond Cond) {
+/// Return the type which the elements of the vector have in the X86
+/// representation of the vector.
+Type InstX86Base::getInVectorElementType(Type Ty) {
+  assert(isVectorType(Ty));
+  assert(Ty < std::size(TypeAttributes));
+  return TypeAttributes[Ty].InVectorElementType;
+}
+
+Cond::BrCond InstX86Base::getOppositeCondition(BrCond Cond) {
   return InstBrAttributes[Cond].Opposite;
 }
 
@@ -239,7 +247,7 @@
                           llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
   constexpr uint16_t Encoded_rAX = 0;
   (void)Encoded_rAX;
-  assert(Traits::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
+  assert(RegX8664::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
   this->addSource(DestOrAddr);
   this->addSource(Eax);
   this->addSource(Desired);
@@ -376,7 +384,7 @@
   if (!BuildDefs::dump())
     return;
   Ostream &Str = Func->getContext()->getStrDump();
-  Str << "[" << Traits::TargetName << "] ";
+  Str << "[X8664] ";
   Inst::dump(Func);
 }
 
@@ -522,7 +530,7 @@
   Operand *Target = getJmpTarget();
   if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
     if (Var->hasReg()) {
-      Asm->jmp(Traits::getEncodedGPR(Var->getRegNum()));
+      Asm->jmp(RegX8664::getEncodedGPR(Var->getRegNum()));
     } else {
       // The jmp instruction with a memory operand should be possible to
       // encode, but it isn't a valid sandboxed instruction, and there
@@ -581,7 +589,7 @@
   auto *Target = InstX86Base::getTarget(Func);
   if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
     if (Var->hasReg()) {
-      Asm->call(Traits::getEncodedGPR(Var->getRegNum()));
+      Asm->call(RegX8664::getEncodedGPR(Var->getRegNum()));
     } else {
       Asm->call(AsmAddress(Var, Target));
     }
@@ -637,7 +645,7 @@
   if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
     if (Var->hasReg()) {
       // We cheat a little and use GPRRegister even for byte operations.
-      GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
+      GPRRegister VarReg = RegX8664::getEncodedGPR(Var->getRegNum());
       (Asm->*(Emitter.Reg))(Ty, VarReg);
     } else {
       AsmAddress StackAddr(AsmAddress(Var, Target));
@@ -658,13 +666,13 @@
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(Var->hasReg());
   // We cheat a little and use GPRRegister even for byte operations.
-  GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
-                                    : Traits::getEncodedGPR(Var->getRegNum());
+  GPRRegister VarReg = VarCanBeByte ? RegX8664::getEncodedGPR(Var->getRegNum())
+                                    : RegX8664::getEncodedGPR(Var->getRegNum());
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
       GPRRegister SrcReg = SrcCanBeByte
-                               ? Traits::getEncodedGPR(SrcVar->getRegNum())
-                               : Traits::getEncodedGPR(SrcVar->getRegNum());
+                               ? RegX8664::getEncodedGPR(SrcVar->getRegNum())
+                               : RegX8664::getEncodedGPR(SrcVar->getRegNum());
       (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
     } else {
       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
@@ -696,7 +704,7 @@
   // Src can only be Reg or AssemblerImmediate.
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     assert(SrcVar->hasReg());
-    GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
+    GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar->getRegNum());
     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
@@ -738,11 +746,11 @@
   // extend this to check Dest if we decide to use that form.
   assert(Var->hasReg());
   // We cheat a little and use GPRRegister even for byte operations.
-  GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
+  GPRRegister VarReg = RegX8664::getEncodedGPR(Var->getRegNum());
   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     assert(SrcVar->hasReg());
-    GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
+    GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar->getRegNum());
     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
@@ -760,11 +768,11 @@
   Assembler *Asm = Func->getAssembler<Assembler>();
   // Dest can be reg or mem, but we only use the reg variant.
   assert(Dest->hasReg());
-  GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
+  GPRRegister DestReg = RegX8664::getEncodedGPR(Dest->getRegNum());
   // SrcVar1 must be reg.
   const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
   assert(SrcVar1->hasReg());
-  GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar1->getRegNum());
+  GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar1->getRegNum());
   Type Ty = SrcVar1->getType();
   // Src2 can be the implicit CL register or an immediate.
   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
@@ -781,10 +789,10 @@
   auto *Target = InstX86Base::getTarget(Func);
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(Var->hasReg());
-  XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
+  XmmRegister VarReg = RegX8664::getEncodedXmm(Var->getRegNum());
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
-      XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+      XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
     } else {
       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
@@ -805,10 +813,10 @@
   auto *Target = InstX86Base::getTarget(Func);
   Assembler *Asm = Func->getAssembler<Assembler>();
   assert(Var->hasReg());
-  XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
+  XmmRegister VarReg = RegX8664::getEncodedXmm(Var->getRegNum());
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
-      XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+      XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
     } else {
       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
@@ -884,11 +892,11 @@
   auto *Target = InstX86Base::getTarget(Func);
   Assembler *Asm = Func->getAssembler<Assembler>();
   if (Dest->hasReg()) {
-    XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
+    XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
     if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
       if (SrcVar->hasReg()) {
         (Asm->*(Emitter.XmmXmm))(DestReg,
-                                 Traits::getEncodedXmm(SrcVar->getRegNum()));
+                                 RegX8664::getEncodedXmm(SrcVar->getRegNum()));
       } else {
         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
@@ -905,7 +913,7 @@
     const auto *SrcVar = llvm::cast<Variable>(Src);
     assert(SrcVar->hasReg());
     (Asm->*(Emitter.AddrXmm))(StackAddr,
-                              Traits::getEncodedXmm(SrcVar->getRegNum()));
+                              RegX8664::getEncodedXmm(SrcVar->getRegNum()));
   }
 }
 
@@ -956,8 +964,8 @@
   assert(isVectorType(SrcTy));
   assert(isScalarIntegerType(DestTy));
   assert(DestTy == IceType_i32 || DestTy == IceType_i64);
-  XmmRegister SrcReg = Traits::getEncodedXmm(Src->getRegNum());
-  GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
+  XmmRegister SrcReg = RegX8664::getEncodedXmm(Src->getRegNum());
+  GPRRegister DestReg = RegX8664::getEncodedGPR(Dest->getRegNum());
   Asm->movmsk(SrcTy, DestReg, SrcReg);
 }
 
@@ -1137,9 +1145,9 @@
   assert(llvm::isa<Constant>(this->getSrc(1)));
   static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
       &Assembler::imul, &Assembler::imul};
-  emitIASThreeOpImmOps<GPRRegister, GPRRegister, Traits::getEncodedGPR,
-                       Traits::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
-                                              this->getSrc(1), Emitter);
+  emitIASThreeOpImmOps<GPRRegister, GPRRegister, RegX8664::getEncodedGPR,
+                       RegX8664::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
+                                                this->getSrc(1), Emitter);
 }
 
 void InstX86Insertps::emitIAS(const Cfg *Func) const {
@@ -1150,9 +1158,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::insertps, &Assembler::insertps};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
-                                              this->getSrc(2), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
+                       RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
+                                                this->getSrc(2), Emitter);
 }
 
 void InstX86Cbwdq::emit(const Cfg *Func) const {
@@ -1188,8 +1196,8 @@
            "cltd";
     break;
   case IceType_i64:
-    assert(SrcReg == Traits::getRaxOrDie());
-    assert(DestReg == Traits::getRdxOrDie());
+    assert(SrcReg == RegisterSet::Reg_rax);
+    assert(DestReg == RegisterSet::Reg_rdx);
     Str << "\t"
            "cqo";
     break;
@@ -1224,8 +1232,8 @@
     Asm->cdq();
     break;
   case IceType_i64:
-    assert(SrcReg == Traits::getRaxOrDie());
-    assert(DestReg == Traits::getRdxOrDie());
+    assert(SrcReg == RegisterSet::Reg_rax);
+    assert(DestReg == RegisterSet::Reg_rdx);
     Asm->cqo();
     break;
   }
@@ -1369,17 +1377,17 @@
   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     if (SrcVar->hasReg()) {
       Asm->cmov(SrcTy, Condition,
-                Traits::getEncodedGPR(this->getDest()->getRegNum()),
-                Traits::getEncodedGPR(SrcVar->getRegNum()));
+                RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
+                RegX8664::getEncodedGPR(SrcVar->getRegNum()));
     } else {
       Asm->cmov(SrcTy, Condition,
-                Traits::getEncodedGPR(this->getDest()->getRegNum()),
+                RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
                 AsmAddress(SrcVar, Target));
     }
   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
     Asm->cmov(SrcTy, Condition,
-              Traits::getEncodedGPR(this->getDest()->getRegNum()),
+              RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
               AsmAddress(Mem, Asm, Target));
   } else {
     llvm_unreachable("Unexpected operand type");
@@ -1424,12 +1432,12 @@
   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
   if (SrcVar->hasReg()) {
     Asm->cmpps(this->getDest()->getType(),
-               Traits::getEncodedXmm(this->getDest()->getRegNum()),
-               Traits::getEncodedXmm(SrcVar->getRegNum()), Condition);
+               RegX8664::getEncodedXmm(this->getDest()->getRegNum()),
+               RegX8664::getEncodedXmm(SrcVar->getRegNum()), Condition);
   } else {
     AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
     Asm->cmpps(this->getDest()->getType(),
-               Traits::getEncodedXmm(this->getDest()->getRegNum()),
+               RegX8664::getEncodedXmm(this->getDest()->getRegNum()),
                SrcStackAddr, Condition);
   }
 }
@@ -1473,7 +1481,7 @@
   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
   const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
   assert(VarReg->hasReg());
-  const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
+  const GPRRegister Reg = RegX8664::getEncodedGPR(VarReg->getRegNum());
   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
 }
 
@@ -1552,9 +1560,9 @@
     assert(isScalarFloatingType(DestTy));
     static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
         &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
-    emitIASCastRegOp<XmmRegister, GPRRegister, Traits::getEncodedXmm,
-                     Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
-                                            Emitter);
+    emitIASCastRegOp<XmmRegister, GPRRegister, RegX8664::getEncodedXmm,
+                     RegX8664::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
+                                              Emitter);
     return;
   }
   case Tss2si: {
@@ -1563,9 +1571,9 @@
     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
         &Assembler::cvttss2si, &Assembler::cvttss2si};
-    emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
-                     Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
-                                            Emitter);
+    emitIASCastRegOp<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
+                     RegX8664::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
+                                              Emitter);
     return;
   }
   case Ss2si: {
@@ -1574,9 +1582,9 @@
     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
         &Assembler::cvtss2si, &Assembler::cvtss2si};
-    emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
-                     Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
-                                            Emitter);
+    emitIASCastRegOp<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
+                     RegX8664::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
+                                              Emitter);
     return;
   }
   case Float2float: {
@@ -1649,9 +1657,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::round, &Assembler::round};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
-                                              this->getSrc(1), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
+                       RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
+                                                this->getSrc(1), Emitter);
 }
 
 void InstX86Icmp::emit(const Cfg *Func) const {
@@ -1852,7 +1860,7 @@
     // Src must be a register, since Dest is a Mem operand of some kind.
     const auto *SrcVar = llvm::cast<Variable>(Src);
     assert(SrcVar->hasReg());
-    XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+    XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
     Assembler *Asm = Func->getAssembler<Assembler>();
     auto *Target = InstX86Base::getTarget(Func);
     if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
@@ -1905,7 +1913,7 @@
   assert(SrcVar->hasReg());
   auto *Target = InstX86Base::getTarget(Func);
   Asm->movups(AsmAddress(DestMem, Asm, Target),
-              Traits::getEncodedXmm(SrcVar->getRegNum()));
+              RegX8664::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86StoreP::dump(const Cfg *Func) const {
@@ -1942,7 +1950,7 @@
   assert(SrcVar->hasReg());
   auto *Target = InstX86Base::getTarget(Func);
   Asm->movq(AsmAddress(DestMem, Asm, Target),
-            Traits::getEncodedXmm(SrcVar->getRegNum()));
+            RegX8664::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86StoreQ::dump(const Cfg *Func) const {
@@ -1979,7 +1987,7 @@
   assert(SrcVar->hasReg());
   auto *Target = InstX86Base::getTarget(Func);
   Asm->movd(SrcVar->getType(), AsmAddress(DestMem, Asm, Target),
-            Traits::getEncodedXmm(SrcVar->getRegNum()));
+            RegX8664::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86StoreD::dump(const Cfg *Func) const {
@@ -2082,7 +2090,7 @@
   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
     RegNumT NewRegNum;
     if (SrcVar->hasReg())
-      NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
+      NewRegNum = RegX8664::getGprForType(DestTy, SrcVar->getRegNum());
     if (SrcTy != DestTy)
       NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
   }
@@ -2128,7 +2136,7 @@
       if (DestTy == IceType_i64) {
         if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
           Func->getAssembler<Assembler>()->movabs(
-              Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue());
+              RegX8664::getEncodedGPR(Dest->getRegNum()), C64->getValue());
           return;
         }
       }
@@ -2147,14 +2155,15 @@
       const auto *SrcVar = llvm::cast<Variable>(Src);
       assert(SrcVar->hasReg());
       Assembler *Asm = Func->getAssembler<Assembler>();
-      Asm->movss(SrcTy, StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
+      Asm->movss(SrcTy, StackAddr,
+                 RegX8664::getEncodedXmm(SrcVar->getRegNum()));
       return;
     } else if (isVectorType(SrcTy)) {
       // Src must be a register
       const auto *SrcVar = llvm::cast<Variable>(Src);
       assert(SrcVar->hasReg());
       Assembler *Asm = Func->getAssembler<Assembler>();
-      Asm->movups(StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
+      Asm->movups(StackAddr, RegX8664::getEncodedXmm(SrcVar->getRegNum()));
     } else {
       // Src can be a register or immediate.
       assert(isScalarIntegerType(SrcTy));
@@ -2202,10 +2211,10 @@
               typeWidthInBytes(SrcVar->getType()) ==
                   typeWidthInBytes(Dest->getType())));
       assert(Dest->hasReg());
-      XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
+      XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
       if (SrcVar->hasReg()) {
         Asm->movd(SrcVar->getType(), DestReg,
-                  Traits::getEncodedGPR(SrcVar->getRegNum()));
+                  RegX8664::getEncodedGPR(SrcVar->getRegNum()));
       } else {
         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
         Asm->movd(SrcVar->getType(), DestReg, StackAddr);
@@ -2217,9 +2226,9 @@
                   typeWidthInBytes(Dest->getType())));
       assert(SrcVar->hasReg());
       assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i64);
-      XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
+      XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
       if (Dest->hasReg()) {
-        Asm->movd(Dest->getType(), Traits::getEncodedGPR(Dest->getRegNum()),
+        Asm->movd(Dest->getType(), RegX8664::getEncodedGPR(Dest->getRegNum()),
                   SrcReg);
       } else {
         AsmAddress StackAddr(AsmAddress(Dest, Target));
@@ -2228,7 +2237,7 @@
     }
   } else {
     assert(Dest->hasReg());
-    XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
+    XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
     auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
     Asm->movd(Mem->getType(), DestReg, AsmAddress(Mem, Asm, Target));
   }
@@ -2295,8 +2304,8 @@
   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
   assert(Dest->hasReg() && SrcVar->hasReg());
   Assembler *Asm = Func->getAssembler<Assembler>();
-  Asm->movss(IceType_f32, Traits::getEncodedXmm(Dest->getRegNum()),
-             Traits::getEncodedXmm(SrcVar->getRegNum()));
+  Asm->movss(IceType_f32, RegX8664::getEncodedXmm(Dest->getRegNum()),
+             RegX8664::getEncodedXmm(SrcVar->getRegNum()));
 }
 
 void InstX86Movsx::emitIAS(const Cfg *Func) const {
@@ -2326,8 +2335,8 @@
     return false;
 
   // Reg/reg move with different source and dest can't be elided.
-  if (Traits::getEncodedGPR(Src->getRegNum()) !=
-      Traits::getEncodedGPR(Dest->getRegNum()))
+  if (RegX8664::getEncodedGPR(Src->getRegNum()) !=
+      RegX8664::getEncodedGPR(Dest->getRegNum()))
     return false;
 
   // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
@@ -2353,7 +2362,7 @@
       Src->emit(Func);
       Str << ", ";
       Dest->asType(Func, IceType_i32,
-                   Traits::getGprForType(IceType_i32, Dest->getRegNum()))
+                   RegX8664::getGprForType(IceType_i32, Dest->getRegNum()))
           ->emit(Func);
       Str << " /* movzx */";
     }
@@ -2423,7 +2432,7 @@
   assert(this->getSrcSize() == 2);
   // pextrb and pextrd are SSE4.1 instructions.
   const Variable *Dest = this->getDest();
-  Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType());
+  Type DispatchTy = getInVectorElementType(this->getSrc(0)->getType());
   // pextrw must take a register dest. There is an SSE4.1 version that takes a
   // memory dest, but we aren't using it. For uniformity, just restrict them
   // all to have a register dest for now.
@@ -2432,8 +2441,8 @@
   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
   static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
       &Assembler::pextr, nullptr};
-  emitIASThreeOpImmOps<GPRRegister, XmmRegister, Traits::getEncodedGPR,
-                       Traits::getEncodedXmm>(
+  emitIASThreeOpImmOps<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
+                       RegX8664::getEncodedXmm>(
       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
 }
 
@@ -2450,7 +2459,7 @@
   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
     // If src1 is a register, it should always be r32.
     if (Src1Var->hasReg()) {
-      const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
+      const auto NewRegNum = RegX8664::getBaseReg(Src1Var->getRegNum());
       const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
       NewSrc->emit(Func);
     } else {
@@ -2477,18 +2486,18 @@
     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
       if (Src0Var->hasReg()) {
         const auto RegNum = Src0Var->getRegNum();
-        const auto BaseRegNum = Traits::getBaseReg(RegNum);
+        const auto BaseRegNum = RegX8664::getBaseReg(RegNum);
         (void)BaseRegNum;
-        assert(Traits::getEncodedGPR(RegNum) ==
-               Traits::getEncodedGPR(BaseRegNum));
+        assert(RegX8664::getEncodedGPR(RegNum) ==
+               RegX8664::getEncodedGPR(BaseRegNum));
       }
     }
   }
   static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
       &Assembler::pinsr, &Assembler::pinsr};
-  emitIASThreeOpImmOps<XmmRegister, GPRRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedGPR>(Func, DispatchTy, this->getDest(),
-                                              Src0, this->getSrc(2), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, GPRRegister, RegX8664::getEncodedXmm,
+                       RegX8664::getEncodedGPR>(
+      Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
 }
 
 void InstX86Pshufd::emitIAS(const Cfg *Func) const {
@@ -2497,9 +2506,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::pshufd, &Assembler::pshufd};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
-                                              this->getSrc(1), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
+                       RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
+                                                this->getSrc(1), Emitter);
 }
 
 void InstX86Shufps::emitIAS(const Cfg *Func) const {
@@ -2509,9 +2518,9 @@
   Type Ty = Dest->getType();
   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
       &Assembler::shufps, &Assembler::shufps};
-  emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
-                       Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
-                                              this->getSrc(2), Emitter);
+  emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
+                       RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
+                                                this->getSrc(2), Emitter);
 }
 
 void InstX86Pop::emit(const Cfg *Func) const {
@@ -2528,7 +2537,7 @@
   assert(this->getSrcSize() == 0);
   Assembler *Asm = Func->getAssembler<Assembler>();
   if (this->getDest()->hasReg()) {
-    Asm->popl(Traits::getEncodedGPR(this->getDest()->getRegNum()));
+    Asm->popl(RegX8664::getEncodedGPR(this->getDest()->getRegNum()));
   } else {
     auto *Target = InstX86Base::getTarget(Func);
     Asm->popl(AsmAddress(this->getDest(), Target));
@@ -2562,7 +2571,7 @@
   const Operand *Src = this->getSrc(0);
 
   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
-    Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
+    Asm->pushl(RegX8664::getEncodedGPR(Var->getRegNum()));
   } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
     Asm->pushl(AssemblerImmediate(Const32->getValue()));
   } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
@@ -2621,7 +2630,7 @@
   auto *Target = InstX86Base::getTarget(Func);
   if (this->getDest()->hasReg())
     Asm->setcc(Condition,
-               Traits::getEncodedByteReg(this->getDest()->getRegNum()));
+               RegX8664::getEncodedByteReg(this->getDest()->getRegNum()));
   else
     Asm->setcc(Condition, AsmAddress(this->getDest(), Target));
   return;
@@ -2661,7 +2670,7 @@
   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
   const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
   assert(VarReg->hasReg());
-  const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
+  const GPRRegister Reg = RegX8664::getEncodedGPR(VarReg->getRegNum());
   Asm->xadd(Ty, Addr, Reg, this->Locked);
 }
 
@@ -2695,11 +2704,11 @@
   Type Ty = this->getSrc(0)->getType();
   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
   assert(VarReg1->hasReg());
-  const GPRRegister Reg1 = Traits::getEncodedGPR(VarReg1->getRegNum());
+  const GPRRegister Reg1 = RegX8664::getEncodedGPR(VarReg1->getRegNum());
 
   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
     assert(VarReg0->hasReg());
-    const GPRRegister Reg0 = Traits::getEncodedGPR(VarReg0->getRegNum());
+    const GPRRegister Reg0 = RegX8664::getEncodedGPR(VarReg0->getRegNum());
     Asm->xchg(Ty, Reg0, Reg1);
     return;
   }
@@ -2847,14 +2856,13 @@
       // X86-64 is ILP32, but %rsp and %rbp are accessed as 64-bit registers.
       // For filetype=asm, they need to be emitted as their 32-bit siblings.
       assert(Base->getType() == IceType_i64);
-      assert(Traits::getEncodedGPR(Base->getRegNum()) ==
+      assert(RegX8664::getEncodedGPR(Base->getRegNum()) ==
                  RegX8664::Encoded_Reg_rsp ||
-             Traits::getEncodedGPR(Base->getRegNum()) ==
+             RegX8664::getEncodedGPR(Base->getRegNum()) ==
                  RegX8664::Encoded_Reg_rbp ||
              getType() == IceType_void);
-      B = B->asType(
-          Func, IceType_i32,
-          X8664::Traits::getGprForType(IceType_i32, Base->getRegNum()));
+      B = B->asType(Func, IceType_i32,
+                    RegX8664::getGprForType(IceType_i32, Base->getRegNum()));
     }
 
     B->emit(Func);
@@ -2877,10 +2885,8 @@
   bool Dumped = false;
   Str << "[";
   int32_t Disp = 0;
-  const auto *Target =
-      static_cast<const ::Ice::X8664::TargetX8664 *>(Func->getTarget());
   if (getBase() && getBase()->isRematerializable()) {
-    Disp += getBase()->getRematerializableOffset(Target);
+    Disp += getBase()->getRematerializableOffset(Func->getTarget());
   }
   if (Base) {
     if (Func)
diff --git a/third_party/subzero/src/IceInstX8664.h b/third_party/subzero/src/IceInstX8664.h
index 42201ec..bb21700 100644
--- a/third_party/subzero/src/IceInstX8664.h
+++ b/third_party/subzero/src/IceInstX8664.h
@@ -11,16 +11,11 @@
 /// \brief This file defines the InstX86Base template class, as well as the
 /// generic X86 Instruction class hierarchy.
 ///
-/// Only X86 instructions common across all/most X86 targets should be defined
-/// here, with target-specific instructions declared in the target's traits.
-///
 //===----------------------------------------------------------------------===//
 
 #ifndef SUBZERO_SRC_ICEINSTX8664_H
 #define SUBZERO_SRC_ICEINSTX8664_H
 
-#include "IceTargetLoweringX8664Traits.h"
-
 #include "IceAssemblerX8664.h"
 #include "IceDefs.h"
 #include "IceInst.h"
@@ -30,14 +25,14 @@
 namespace Ice {
 namespace X8664 {
 
-using Traits = TargetX8664Traits;
 using Assembler = AssemblerX8664;
 using AssemblerImmediate = Assembler::Immediate;
 using TargetLowering = TargetX8664;
 
-using GPRRegister = typename Traits::RegisterSet::GPRRegister;
-using RegisterSet = typename Traits::RegisterSet;
-using XmmRegister = typename Traits::RegisterSet::XmmRegister;
+using RegisterSet = ::Ice::RegX8664;
+using GPRRegister = RegisterSet::GPRRegister;
+using ByteRegister = RegisterSet::ByteRegister;
+using XmmRegister = RegisterSet::XmmRegister;
 
 using Cond = CondX86;
 using BrCond = Cond::BrCond;
@@ -264,6 +259,7 @@
   static const char *getWidthString(Type Ty);
   static const char *getFldString(Type Ty);
   static const char *getSseSuffixString(Type DestTy, SseSuffix Suffix);
+  static Type getInVectorElementType(Type Ty);
   static BrCond getOppositeCondition(BrCond Cond);
   void dump(const Cfg *Func) const override;
 
@@ -1078,8 +1074,9 @@
         //                    is handled by Inst86Zext.
         const auto SrcReg = SrcVar->getRegNum();
         const auto DestReg = this->Dest->getRegNum();
-        return (Traits::getEncoding(SrcReg) == Traits::getEncoding(DestReg)) &&
-               (Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg));
+        return (RegX8664::getEncoding(SrcReg) ==
+                RegX8664::getEncoding(DestReg)) &&
+               (RegX8664::getBaseReg(SrcReg) == RegX8664::getBaseReg(DestReg));
       }
     }
     return checkForRedundantAssign(this->getDest(), this->getSrc(0));
@@ -2707,10 +2704,10 @@
   InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem);
 };
 
-/// This is essentially a vector "mov" instruction with an typename
-/// X86OperandMem operand instead of Variable as the destination. It's
-/// important for liveness that there is no Dest operand. The source must be
-/// an Xmm register, since Dest is mem.
+/// This is essentially a vector "mov" instruction with an X86OperandMem operand
+/// instead of Variable as the destination. It's important for liveness that
+/// there is no Dest operand. The source must be an Xmm register, since Dest is
+/// mem.
 class InstX86StoreP final : public InstX86Base {
   InstX86StoreP() = delete;
   InstX86StoreP(const InstX86StoreP &) = delete;
@@ -3059,10 +3056,6 @@
                             InstX86Base::SseSuffix::Pack>(Func, Dest, Source) {}
 };
 
-/// struct Insts is a template that can be used to instantiate all the X86
-/// instructions for a target with a simple
-///
-/// using Insts = ::Ice::X8664::Insts<TraitsType>;
 struct Insts {
   using FakeRMW = InstX86FakeRMW;
   using Label = InstX86Label;
diff --git a/third_party/subzero/src/IceRegistersX8632.h b/third_party/subzero/src/IceRegistersX8632.h
index bb614e0..83773bb 100644
--- a/third_party/subzero/src/IceRegistersX8632.h
+++ b/third_party/subzero/src/IceRegistersX8632.h
@@ -15,11 +15,17 @@
 #ifndef SUBZERO_SRC_ICEREGISTERSX8632_H
 #define SUBZERO_SRC_ICEREGISTERSX8632_H
 
+#include "IceBitVector.h"
 #include "IceDefs.h"
 #include "IceInstX8632.def"
+#include "IceTargetLowering.h"
+#include "IceTargetLoweringX86RegClass.h"
 #include "IceTypes.h"
 
+#include <initializer_list>
+
 namespace Ice {
+using namespace ::Ice::X86;
 
 class RegX8632 {
 public:
@@ -85,6 +91,323 @@
     assert(X87RegNum <= Encoded_X87ST_Last);
     return X87STRegister(X87RegNum);
   }
+
+  static inline const char *getRegName(RegNumT RegNum) {
+    static const char *const RegNames[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  name,
+        REGX8632_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    return RegNames[RegNum];
+  }
+
+  static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
+    static const GPRRegister GPRRegs[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
+        REGX8632_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
+    return GPRRegs[RegNum];
+  }
+
+  static inline ByteRegister getEncodedByteReg(RegNumT RegNum) {
+    static const ByteRegister ByteRegs[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
+        REGX8632_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
+    return ByteRegs[RegNum];
+  }
+
+  static inline bool isXmm(RegNumT RegNum) {
+    static const bool IsXmm[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  isXmm,
+        REGX8632_TABLE
+#undef X
+    };
+    return IsXmm[RegNum];
+  }
+
+  static inline XmmRegister getEncodedXmm(RegNumT RegNum) {
+    static const XmmRegister XmmRegs[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
+        REGX8632_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
+    return XmmRegs[RegNum];
+  }
+
+  static inline uint32_t getEncoding(RegNumT RegNum) {
+    static const uint32_t Encoding[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  encode,
+        REGX8632_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    return Encoding[RegNum];
+  }
+
+  static inline RegNumT getBaseReg(RegNumT RegNum) {
+    static const RegNumT BaseRegs[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  base,
+        REGX8632_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    return BaseRegs[RegNum];
+  }
+
+private:
+  static inline AllRegisters getFirstGprForType(Type Ty) {
+    switch (Ty) {
+    default:
+      llvm_unreachable("Invalid type for GPR.");
+    case IceType_i1:
+    case IceType_i8:
+      return Reg_al;
+    case IceType_i16:
+      return Reg_ax;
+    case IceType_i32:
+      return Reg_eax;
+    }
+  }
+
+public:
+  // Return a register in RegNum's alias set that is suitable for Ty.
+  static inline RegNumT getGprForType(Type Ty, RegNumT RegNum) {
+    assert(RegNum.hasValue());
+
+    if (!isScalarIntegerType(Ty)) {
+      return RegNum;
+    }
+
+    // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions.
+    switch (RegNum) {
+    default:
+      break;
+    case Reg_ah:
+    case Reg_bh:
+    case Reg_ch:
+    case Reg_dh:
+      assert(isByteSizedType(Ty));
+      return RegNum;
+    }
+
+    const AllRegisters FirstGprForType = getFirstGprForType(Ty);
+
+    switch (RegNum) {
+    default:
+      llvm::report_fatal_error("Unknown register.");
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  case val: {                                                                  \
+    if (!isGPR)                                                                \
+      return val;                                                              \
+    assert((is32) || (is16) || (is8) || getBaseReg(val) == Reg_esp);           \
+    constexpr AllRegisters FirstGprWithRegNumSize =                            \
+        (((is32) || val == Reg_esp)                                            \
+             ? Reg_eax                                                         \
+             : (((is16) || val == Reg_sp) ? Reg_ax : Reg_al));                 \
+    const RegNumT NewRegNum =                                                  \
+        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
+    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
+           "Error involving " #val);                                           \
+    return NewRegNum;                                                          \
+  }
+      REGX8632_TABLE
+#undef X
+    }
+  }
+
+public:
+  static inline void
+  initRegisterSet(const ::Ice::ClFlags & /*Flags*/,
+                  std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
+                  std::array<SmallBitVector, Reg_NUM> *RegisterAliases) {
+    SmallBitVector IntegerRegistersI32(Reg_NUM);
+    SmallBitVector IntegerRegistersI16(Reg_NUM);
+    SmallBitVector IntegerRegistersI8(Reg_NUM);
+    SmallBitVector FloatRegisters(Reg_NUM);
+    SmallBitVector VectorRegisters(Reg_NUM);
+    SmallBitVector Trunc64To8Registers(Reg_NUM);
+    SmallBitVector Trunc32To8Registers(Reg_NUM);
+    SmallBitVector Trunc16To8Registers(Reg_NUM);
+    SmallBitVector Trunc8RcvrRegisters(Reg_NUM);
+    SmallBitVector AhRcvrRegisters(Reg_NUM);
+    SmallBitVector InvalidRegisters(Reg_NUM);
+
+    static constexpr struct {
+      uint16_t Val;
+      unsigned Is64 : 1;
+      unsigned Is32 : 1;
+      unsigned Is16 : 1;
+      unsigned Is8 : 1;
+      unsigned IsXmm : 1;
+      unsigned Is64To8 : 1;
+      unsigned Is32To8 : 1;
+      unsigned Is16To8 : 1;
+      unsigned IsTrunc8Rcvr : 1;
+      unsigned IsAhRcvr : 1;
+#define NUM_ALIASES_BITS 2
+      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
+      uint16_t Aliases[1 << NUM_ALIASES_BITS];
+#undef NUM_ALIASES_BITS
+    } X8632RegTable[Reg_NUM] = {
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,      \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,       \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                      \
+  {                                                                             \
+      val,          is64,     is32,                                             \
+      is16,         is8,      isXmm,                                            \
+      is64To8,      is32To8,  is16To8,                                          \
+      isTrunc8Rcvr, isAhRcvr, (std::initializer_list<uint16_t> aliases).size(), \
+      aliases,                                                                  \
+  },
+        REGX8632_TABLE
+#undef X
+    };
+
+    for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) {
+      const auto &Entry = X8632RegTable[ii];
+      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
+      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
+      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
+      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
+      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
+      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
+      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
+      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
+      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
+      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
+      (*RegisterAliases)[Entry.Val].resize(Reg_NUM);
+      for (SizeT J = 0; J < Entry.NumAliases; J++) {
+        SizeT Alias = Entry.Aliases[J];
+        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
+        (*RegisterAliases)[Entry.Val].set(Alias);
+      }
+      (*RegisterAliases)[Entry.Val].set(Entry.Val);
+    }
+
+    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
+    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
+    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
+    (*TypeToRegisterSet)[RC_i64] = InvalidRegisters;
+    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
+    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
+    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
+    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
+    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
+    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
+    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
+    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
+  }
+
+  static inline SmallBitVector
+  getRegisterSet(const ::Ice::ClFlags & /*Flags*/,
+                 TargetLowering::RegSetMask Include,
+                 TargetLowering::RegSetMask Exclude) {
+    SmallBitVector Registers(Reg_NUM);
+
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
+          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
+  if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
+    Registers[val] = true;                                                     \
+  if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
+    Registers[val] = true;                                                     \
+  if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
+    Registers[val] = true;                                                     \
+  if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
+    Registers[val] = true;                                                     \
+  if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
+    Registers[val] = false;                                                    \
+  if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
+    Registers[val] = false;                                                    \
+  if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
+    Registers[val] = false;                                                    \
+  if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
+    Registers[val] = false;
+
+    REGX8632_TABLE
+
+#undef X
+
+    return Registers;
+  }
+
+  // x86-32 calling convention:
+  //
+  // * The first four arguments of vector type, regardless of their position
+  // relative to the other arguments in the argument list, are placed in
+  // registers xmm0 - xmm3.
+  //
+  // This intends to match the section "IA-32 Function Calling Convention" of
+  // the document "OS X ABI Function Call Guide" by Apple.
+
+  /// The maximum number of arguments to pass in XMM registers
+  static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
+  /// The maximum number of arguments to pass in GPR registers
+  static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
+  /// Get the register for a given argument slot in the XMM registers.
+  static inline RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
+    // TODO(sehr): Change to use the CCArg technique used in ARM32.
+    static_assert(Reg_xmm0 + 1 == Reg_xmm1,
+                  "Inconsistency between XMM register numbers and ordinals");
+    if (ArgNum >= X86_MAX_XMM_ARGS) {
+      return RegNumT();
+    }
+    return RegNumT::fixme(Reg_xmm0 + ArgNum);
+  }
+  /// Get the register for a given argument slot in the GPRs.
+  static inline RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+    assert(Ty == IceType_i64 || Ty == IceType_i32);
+    (void)Ty;
+    (void)ArgNum;
+    return RegNumT();
+  }
+  // Given the absolute argument position and argument position by type, return
+  // the register index to assign it to.
+  static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
+    (void)argPos;
+    return argPosByType;
+  };
 };
 
 } // end of namespace Ice
diff --git a/third_party/subzero/src/IceRegistersX8664.h b/third_party/subzero/src/IceRegistersX8664.h
index 692d2f9..9c16953 100644
--- a/third_party/subzero/src/IceRegistersX8664.h
+++ b/third_party/subzero/src/IceRegistersX8664.h
@@ -15,11 +15,17 @@
 #ifndef SUBZERO_SRC_ICEREGISTERSX8664_H
 #define SUBZERO_SRC_ICEREGISTERSX8664_H
 
+#include "IceBitVector.h"
 #include "IceDefs.h"
 #include "IceInstX8664.def"
+#include "IceTargetLowering.h"
+#include "IceTargetLoweringX86RegClass.h"
 #include "IceTypes.h"
 
+#include <initializer_list>
+
 namespace Ice {
+using namespace ::Ice::X86;
 
 class RegX8664 {
 public:
@@ -70,6 +76,394 @@
 #undef X
         Encoded_Not_ByteReg = -1
   };
+
+  static inline const char *getRegName(RegNumT RegNum) {
+    static const char *const RegNames[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)                            \
+  name,
+        REGX8664_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    return RegNames[RegNum];
+  }
+
+  static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
+    static const GPRRegister GPRRegs[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)                            \
+  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
+        REGX8664_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
+    return GPRRegs[RegNum];
+  }
+
+  static inline ByteRegister getEncodedByteReg(RegNumT RegNum) {
+    static const ByteRegister ByteRegs[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)                            \
+  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
+        REGX8664_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
+    return ByteRegs[RegNum];
+  }
+
+  static inline bool isXmm(RegNumT RegNum) {
+    static const bool IsXmm[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)                            \
+  isXmm,
+        REGX8664_TABLE
+#undef X
+    };
+    return IsXmm[RegNum];
+  }
+
+  static inline XmmRegister getEncodedXmm(RegNumT RegNum) {
+    static const XmmRegister XmmRegs[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)                            \
+  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
+        REGX8664_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
+    return XmmRegs[RegNum];
+  }
+
+  static inline uint32_t getEncoding(RegNumT RegNum) {
+    static const uint32_t Encoding[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,
+        REGX8664_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    return Encoding[RegNum];
+  }
+
+  static inline RegNumT getBaseReg(RegNumT RegNum) {
+    static const RegNumT BaseRegs[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)                            \
+  base,
+        REGX8664_TABLE
+#undef X
+    };
+    RegNum.assertIsValid();
+    return BaseRegs[RegNum];
+  }
+
+private:
+  static inline RegNumT getFirstGprForType(Type Ty) {
+    switch (Ty) {
+    default:
+      llvm_unreachable("Invalid type for GPR.");
+    case IceType_i1:
+    case IceType_i8:
+      return Reg_al;
+    case IceType_i16:
+      return Reg_ax;
+    case IceType_i32:
+      return Reg_eax;
+    case IceType_i64:
+      return Reg_rax;
+    }
+  }
+
+public:
+  static inline RegNumT getGprForType(Type Ty, RegNumT RegNum) {
+    assert(RegNum.hasValue());
+
+    if (!isScalarIntegerType(Ty)) {
+      return RegNum;
+    }
+
+    assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 ||
+           Ty == IceType_i32 || Ty == IceType_i64);
+
+    if (RegNum == Reg_ah) {
+      assert(Ty == IceType_i8);
+      return RegNum;
+    }
+
+    assert(RegNum != Reg_bh);
+    assert(RegNum != Reg_ch);
+    assert(RegNum != Reg_dh);
+
+    const RegNumT FirstGprForType = getFirstGprForType(Ty);
+
+    switch (RegNum) {
+    default:
+      llvm::report_fatal_error("Unknown register.");
+#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
+          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
+          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
+  case val: {                                                                  \
+    if (!isGPR)                                                                \
+      return val;                                                              \
+    assert((is64) || (is32) || (is16) || (is8) || getBaseReg(val) == Reg_rsp); \
+    constexpr AllRegisters FirstGprWithRegNumSize =                            \
+        ((is64) || val == Reg_rsp)                                             \
+            ? Reg_rax                                                          \
+            : (((is32) || val == Reg_esp)                                      \
+                   ? Reg_eax                                                   \
+                   : (((is16) || val == Reg_sp) ? Reg_ax : Reg_al));           \
+    const auto NewRegNum =                                                     \
+        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
+    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
+           "Error involving " #val);                                           \
+    return NewRegNum;                                                          \
+  }
+      REGX8664_TABLE
+#undef X
+    }
+  }
+
+  static inline void
+  initRegisterSet(const ::Ice::ClFlags &Flags,
+                  std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
+                  std::array<SmallBitVector, Reg_NUM> *RegisterAliases) {
+    SmallBitVector IntegerRegistersI64(Reg_NUM);
+    SmallBitVector IntegerRegistersI32(Reg_NUM);
+    SmallBitVector IntegerRegistersI16(Reg_NUM);
+    SmallBitVector IntegerRegistersI8(Reg_NUM);
+    SmallBitVector FloatRegisters(Reg_NUM);
+    SmallBitVector VectorRegisters(Reg_NUM);
+    SmallBitVector Trunc64To8Registers(Reg_NUM);
+    SmallBitVector Trunc32To8Registers(Reg_NUM);
+    SmallBitVector Trunc16To8Registers(Reg_NUM);
+    SmallBitVector Trunc8RcvrRegisters(Reg_NUM);
+    SmallBitVector AhRcvrRegisters(Reg_NUM);
+    SmallBitVector InvalidRegisters(Reg_NUM);
+
+    static constexpr struct {
+      uint16_t Val;
+      unsigned IsReservedWhenSandboxing : 1;
+      unsigned Is64 : 1;
+      unsigned Is32 : 1;
+      unsigned Is16 : 1;
+      unsigned Is8 : 1;
+      unsigned IsXmm : 1;
+      unsigned Is64To8 : 1;
+      unsigned Is32To8 : 1;
+      unsigned Is16To8 : 1;
+      unsigned IsTrunc8Rcvr : 1;
+      unsigned IsAhRcvr : 1;
+#define NUM_ALIASES_BITS 2
+      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
+      uint16_t Aliases[1 << NUM_ALIASES_BITS];
+#undef NUM_ALIASES_BITS
+    } X8664RegTable[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)                            \
+  {                                                                            \
+      val,                                                                     \
+      sboxres,                                                                 \
+      is64,                                                                    \
+      is32,                                                                    \
+      is16,                                                                    \
+      is8,                                                                     \
+      isXmm,                                                                   \
+      is64To8,                                                                 \
+      is32To8,                                                                 \
+      is16To8,                                                                 \
+      isTrunc8Rcvr,                                                            \
+      isAhRcvr,                                                                \
+      (std::initializer_list<uint16_t> aliases).size(),                        \
+      aliases,                                                                 \
+  },
+        REGX8664_TABLE
+#undef X
+    };
+
+    for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) {
+      const auto &Entry = X8664RegTable[ii];
+      // Even though the register is disabled for register allocation, it might
+      // still be used by the Target Lowering (e.g., base pointer), so the
+      // register alias table still needs to be defined.
+      (*RegisterAliases)[Entry.Val].resize(Reg_NUM);
+      for (Ice::SizeT J = 0; J < Entry.NumAliases; ++J) {
+        SizeT Alias = Entry.Aliases[J];
+        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
+        (*RegisterAliases)[Entry.Val].set(Alias);
+      }
+
+      (*RegisterAliases)[Entry.Val].set(Entry.Val);
+
+      (IntegerRegistersI64)[Entry.Val] = Entry.Is64;
+      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
+      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
+      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
+      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
+      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
+      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
+      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
+      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
+      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
+      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
+    }
+
+    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
+    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
+    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
+    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
+    (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64;
+    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
+    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
+    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
+    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
+    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
+    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
+    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
+    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
+    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
+  }
+
+  static inline SmallBitVector
+  getRegisterSet(const ::Ice::ClFlags &Flags,
+                 TargetLowering::RegSetMask Include,
+                 TargetLowering::RegSetMask Exclude) {
+    SmallBitVector Registers(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)                            \
+  if (scratch && (Include & TargetLowering::RegSet_CallerSave))                \
+    Registers[val] = true;                                                     \
+  if (preserved && (Include & TargetLowering::RegSet_CalleeSave))              \
+    Registers[val] = true;                                                     \
+  if (stackptr && (Include & TargetLowering::RegSet_StackPointer))             \
+    Registers[val] = true;                                                     \
+  if (frameptr && (Include & TargetLowering::RegSet_FramePointer))             \
+    Registers[val] = true;                                                     \
+  if (scratch && (Exclude & TargetLowering::RegSet_CallerSave))                \
+    Registers[val] = false;                                                    \
+  if (preserved && (Exclude & TargetLowering::RegSet_CalleeSave))              \
+    Registers[val] = false;                                                    \
+  if (stackptr && (Exclude & TargetLowering::RegSet_StackPointer))             \
+    Registers[val] = false;                                                    \
+  if (frameptr && (Exclude & TargetLowering::RegSet_FramePointer))             \
+    Registers[val] = false;
+
+    REGX8664_TABLE
+
+#undef X
+
+    return Registers;
+  }
+
+#if defined(_WIN64)
+  // Microsoft x86-64 calling convention:
+  //
+  // * The first four arguments of vector/fp type, regardless of their
+  // position relative to the other arguments in the argument list, are placed
+  // in registers %xmm0 - %xmm3.
+  //
+  // * The first four arguments of integer types, regardless of their position
+  // relative to the other arguments in the argument list, are placed in
+  // registers %rcx, %rdx, %r8, and %r9.
+
+  /// The maximum number of arguments to pass in XMM registers
+  static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
+  /// The maximum number of arguments to pass in GPR registers
+  static constexpr uint32_t X86_MAX_GPR_ARGS = 4;
+  static inline RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+    if (ArgNum >= X86_MAX_GPR_ARGS) {
+      return RegNumT();
+    }
+    static const AllRegisters GprForArgNum[] = {
+        Reg_rcx,
+        Reg_rdx,
+        Reg_r8,
+        Reg_r9,
+    };
+    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 RegX8664::getGprForType(Ty, GprForArgNum[ArgNum]);
+  }
+  // Given the absolute argument position and argument position by type, return
+  // the register index to assign it to.
+  static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
+    // Microsoft x64 ABI: register is selected by arg position (e.g. 1st int as
+    // 2nd param goes into 2nd int reg)
+    (void)argPosByType;
+    return argPos;
+  };
+
+#else
+  // System V x86-64 calling convention:
+  //
+  // * The first eight arguments of vector/fp type, regardless of their
+  // position relative to the other arguments in the argument list, are placed
+  // in registers %xmm0 - %xmm7.
+  //
+  // * The first six arguments of integer types, regardless of their position
+  // relative to the other arguments in the argument list, are placed in
+  // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
+  //
+  // This intends to match the section "Function Calling Sequence" of the
+  // document "System V Application Binary Interface."
+
+  /// The maximum number of arguments to pass in XMM registers
+  static constexpr uint32_t X86_MAX_XMM_ARGS = 8;
+  /// The maximum number of arguments to pass in GPR registers
+  static constexpr uint32_t X86_MAX_GPR_ARGS = 6;
+  /// Get the register for a given argument slot in the GPRs.
+  static inline RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
+    if (ArgNum >= X86_MAX_GPR_ARGS) {
+      return RegNumT();
+    }
+    static const AllRegisters GprForArgNum[] = {
+        Reg_rdi, Reg_rsi, Reg_rdx, Reg_rcx, Reg_r8, Reg_r9,
+    };
+    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 RegX8664::getGprForType(Ty, GprForArgNum[ArgNum]);
+  }
+  // Given the absolute argument position and argument position by type, return
+  // the register index to assign it to.
+  static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
+    (void)argPos;
+    return argPosByType;
+  }
+#endif
+
+  /// Get the register for a given argument slot in the XMM registers.
+  static inline RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
+    // TODO(sehr): Change to use the CCArg technique used in ARM32.
+    static_assert(Reg_xmm0 + 1 == Reg_xmm1,
+                  "Inconsistency between XMM register numbers and ordinals");
+    if (ArgNum >= X86_MAX_XMM_ARGS) {
+      return RegNumT();
+    }
+    return RegNumT::fixme(Reg_xmm0 + ArgNum);
+  }
 };
 
 } // end of namespace Ice
diff --git a/third_party/subzero/src/IceTargetLoweringX86.h b/third_party/subzero/src/IceTargetLoweringX86.h
index 75893c5..7868d80 100644
--- a/third_party/subzero/src/IceTargetLoweringX86.h
+++ b/third_party/subzero/src/IceTargetLoweringX86.h
@@ -44,11 +44,10 @@
 
 protected:
   explicit TargetX86(Cfg *Func) : TargetLowering(Func) {
-    static_assert(
-        (InstructionSetX86::End - InstructionSetX86::Begin) ==
-            (TargetInstructionSet::X86InstructionSet_End -
-             TargetInstructionSet::X86InstructionSet_Begin),
-        "Traits::InstructionSet range different from TargetInstructionSet");
+    static_assert((InstructionSetX86::End - InstructionSetX86::Begin) ==
+                      (TargetInstructionSet::X86InstructionSet_End -
+                       TargetInstructionSet::X86InstructionSet_Begin),
+                  "InstructionSet range different from TargetInstructionSet");
     if (getFlags().getTargetInstructionSet() !=
         TargetInstructionSet::BaseInstructionSet) {
       InstructionSet = static_cast<InstructionSetX86>(
diff --git a/third_party/subzero/src/IceTargetLoweringX8632.cpp b/third_party/subzero/src/IceTargetLoweringX8632.cpp
index 349f667..6875c8a 100644
--- a/third_party/subzero/src/IceTargetLoweringX8632.cpp
+++ b/third_party/subzero/src/IceTargetLoweringX8632.cpp
@@ -26,7 +26,7 @@
 #include "IceLiveness.h"
 #include "IceOperand.h"
 #include "IcePhiLoweringImpl.h"
-#include "IceTargetLoweringX8632Traits.h"
+#include "IceTargetLoweringX8632.def"
 #include "IceUtils.h"
 #include "IceVariableSplitting.h"
 
@@ -69,80 +69,22 @@
 namespace Ice {
 namespace X8632 {
 
-template <typename T> struct PoolTypeConverter {};
+/// The number of bits in a byte
+static constexpr uint32_t X86_CHAR_BIT = 8;
+/// Size of the return address on the stack
+static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4;
 
-template <> struct PoolTypeConverter<float> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantFloat;
-  static const Type Ty = IceType_f32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-template <> struct PoolTypeConverter<double> {
-  using PrimitiveIntType = uint64_t;
-  using IceType = ConstantDouble;
-  static const Type Ty = IceType_f64;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint32_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint16_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i16;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint8_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i8;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-const char *PoolTypeConverter<float>::TypeName = "float";
-const char *PoolTypeConverter<float>::AsmTag = ".long";
-const char *PoolTypeConverter<float>::PrintfString = "0x%x";
-
-const char *PoolTypeConverter<double>::TypeName = "double";
-const char *PoolTypeConverter<double>::AsmTag = ".quad";
-const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
-
-const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
-const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
-const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
-
-const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
-const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
-const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
-
-const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
-const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
-const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
+/// \name Limits for unrolling memory intrinsics.
+/// @{
+static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
+static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
+static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
+/// @}
 
 BoolFoldingEntry::BoolFoldingEntry(Inst *I)
     : Instr(I), IsComplex(BoolFolding::hasComplexLowering(I)) {}
 
-typename BoolFolding::BoolFoldingProducerKind
+BoolFolding::BoolFoldingProducerKind
 BoolFolding::getProducerKind(const Inst *Instr) {
   if (llvm::isa<InstIcmp>(Instr)) {
     if (Instr->getSrc(0)->getType() != IceType_i64)
@@ -175,7 +117,7 @@
   return PK_None;
 }
 
-typename BoolFolding::BoolFoldingConsumerKind
+BoolFolding::BoolFoldingConsumerKind
 BoolFolding::getConsumerKind(const Inst *Instr) {
   if (llvm::isa<InstBr>(Instr))
     return CK_Br;
@@ -209,14 +151,14 @@
   case PK_Icmp64:
     return true;
   case PK_Fcmp:
-    return Traits::TableFcmp[llvm::cast<InstFcmp>(Instr)->getCondition()].C2 !=
-           CondX86::Br_None;
+    return TargetX8632::TableFcmp[llvm::cast<InstFcmp>(Instr)->getCondition()]
+               .C2 != CondX86::Br_None;
   }
 }
 
 bool BoolFolding::isValidFolding(
-    typename BoolFolding::BoolFoldingProducerKind ProducerKind,
-    typename BoolFolding::BoolFoldingConsumerKind ConsumerKind) {
+    BoolFolding::BoolFoldingProducerKind ProducerKind,
+    BoolFolding::BoolFoldingConsumerKind ConsumerKind) {
   switch (ProducerKind) {
   default:
     return false;
@@ -255,13 +197,13 @@
         continue;
       }
       // Consumer instructions must be white-listed
-      typename BoolFolding::BoolFoldingConsumerKind ConsumerKind =
+      BoolFolding::BoolFoldingConsumerKind ConsumerKind =
           getConsumerKind(&Instr);
       if (ConsumerKind == CK_None) {
         setInvalid(VarNum);
         continue;
       }
-      typename BoolFolding::BoolFoldingProducerKind ProducerKind =
+      BoolFolding::BoolFoldingProducerKind ProducerKind =
           getProducerKind(Producers[VarNum].Instr);
       if (!isValidFolding(ProducerKind, ConsumerKind)) {
         setInvalid(VarNum);
@@ -365,13 +307,13 @@
 TargetX8632::TargetX8632(Cfg *Func) : TargetX86(Func) {}
 
 void TargetX8632::staticInit(GlobalContext *Ctx) {
-  RegNumT::setLimit(Traits::RegisterSet::Reg_NUM);
-  Traits::initRegisterSet(getFlags(), &TypeToRegisterSet, &RegisterAliases);
+  RegNumT::setLimit(RegX8632::Reg_NUM);
+  RegX8632::initRegisterSet(getFlags(), &TypeToRegisterSet, &RegisterAliases);
   for (size_t i = 0; i < TypeToRegisterSet.size(); ++i)
     TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i];
-  filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM,
-                          TypeToRegisterSet.data(), TypeToRegisterSet.size(),
-                          Traits::getRegName, getRegClassName);
+  filterTypeToRegisterSet(Ctx, RegX8632::Reg_NUM, TypeToRegisterSet.data(),
+                          TypeToRegisterSet.size(), RegX8632::getRegName,
+                          getRegClassName);
 }
 
 bool TargetX8632::shouldBePooled(const Constant *C) {
@@ -693,6 +635,12 @@
     Func->getContext()->unlockStr();
 }
 
+/// Value is in bytes. Return Value adjusted to the next highest multiple of
+/// the stack alignment.
+uint32_t TargetX8632::applyStackAlignment(uint32_t Value) {
+  return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
+}
+
 // Converts a ConstantInteger32 operand into its constant value, or
 // MemoryOrderInvalid if the operand is not a ConstantInteger32.
 inline uint64_t getConstantMemoryOrder(Operand *Opnd) {
@@ -821,7 +769,7 @@
   if (Ty == IceType_void)
     Ty = IceType_i32;
   if (PhysicalRegisters[Ty].empty())
-    PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM);
+    PhysicalRegisters[Ty].resize(RegX8632::Reg_NUM);
   assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
   Variable *Reg = PhysicalRegisters[Ty][RegNum];
   if (Reg == nullptr) {
@@ -835,12 +783,12 @@
     // Don't bother tracking the live range of a named physical register.
     Reg->setIgnoreLiveness();
   }
-  assert(Traits::getGprForType(Ty, RegNum) == RegNum);
+  assert(RegX8632::getGprForType(Ty, RegNum) == RegNum);
   return Reg;
 }
 
 const char *TargetX8632::getRegName(RegNumT RegNum, Type Ty) const {
-  return Traits::getRegName(Traits::getGprForType(Ty, RegNum));
+  return RegX8632::getRegName(RegX8632::getGprForType(Ty, RegNum));
 }
 
 void TargetX8632::emitVariable(const Variable *Var) const {
@@ -867,7 +815,7 @@
   } else if (Offset != 0) {
     Str << Offset;
   }
-  const Type FrameSPTy = Traits::WordType;
+  const Type FrameSPTy = WordType;
   Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")";
 }
 
@@ -965,19 +913,19 @@
   size_t PreservedRegsSizeBytes = 0;
   SmallBitVector Pushed(CalleeSaves.size());
   for (RegNumT i : RegNumBVIter(CalleeSaves)) {
-    const auto Canonical = Traits::getBaseReg(i);
-    assert(Canonical == Traits::getBaseReg(Canonical));
+    const auto Canonical = RegX8632::getBaseReg(i);
+    assert(Canonical == RegX8632::getBaseReg(Canonical));
     if (RegsUsed[i]) {
       Pushed[Canonical] = true;
     }
   }
   for (RegNumT RegNum : RegNumBVIter(Pushed)) {
-    assert(RegNum == Traits::getBaseReg(RegNum));
+    assert(RegNum == RegX8632::getBaseReg(RegNum));
     ++NumCallee;
-    if (Traits::isXmm(RegNum)) {
+    if (RegX8632::isXmm(RegNum)) {
       PreservedRegsSizeBytes += 16;
     } else {
-      PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType);
+      PreservedRegsSizeBytes += typeWidthInBytes(WordType);
     }
     _push_reg(RegNum);
   }
@@ -990,7 +938,7 @@
     assert(
         (RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)).count() ==
         0);
-    PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType);
+    PreservedRegsSizeBytes += typeWidthInBytes(WordType);
     _link_bp();
   }
 
@@ -1001,7 +949,7 @@
   assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes);
   uint32_t SpillAreaPaddingBytes = 0;
   uint32_t LocalsSlotsPaddingBytes = 0;
-  alignStackSpillAreas(Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes,
+  alignStackSpillAreas(X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes,
                        SpillAreaAlignmentBytes, GlobalsSize,
                        LocalsSlotsAlignmentBytes, &SpillAreaPaddingBytes,
                        &LocalsSlotsPaddingBytes);
@@ -1014,14 +962,12 @@
   // This is done by a movp[sd] and an fld[sd].  Ensure there is enough scratch
   // space on the stack for this.
   const Type ReturnType = Func->getReturnType();
-  if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-    if (isScalarFloatingType(ReturnType)) {
-      // Avoid misaligned double-precision load/store.
-      RequiredStackAlignment = std::max<size_t>(
-          RequiredStackAlignment, Traits::X86_STACK_ALIGNMENT_BYTES);
-      SpillAreaSizeBytes =
-          std::max(typeWidthInBytesOnStack(ReturnType), SpillAreaSizeBytes);
-    }
+  if (isScalarFloatingType(ReturnType)) {
+    // Avoid misaligned double-precision load/store.
+    RequiredStackAlignment =
+        std::max<size_t>(RequiredStackAlignment, X86_STACK_ALIGNMENT_BYTES);
+    SpillAreaSizeBytes =
+        std::max(typeWidthInBytesOnStack(ReturnType), SpillAreaSizeBytes);
   }
 
   RequiredStackAlignment =
@@ -1042,8 +988,7 @@
   // Note that StackOffset does not include spill area. It's the offset from the
   // base stack pointer (epb), whether we set it or not, to the the first stack
   // arg (if any). StackSize, on the other hand, does include the spill area.
-  const uint32_t StackOffset =
-      Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes;
+  const uint32_t StackOffset = X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes;
   uint32_t StackSize = Utils::applyAlignment(StackOffset + SpillAreaSizeBytes,
                                              RequiredStackAlignment);
   StackSize = Utils::applyAlignment(StackSize + maxOutArgsSizeBytes(),
@@ -1066,9 +1011,9 @@
 
   // If the required alignment is greater than the stack pointer's guaranteed
   // alignment, align the stack pointer accordingly.
-  if (RequiredStackAlignment > Traits::X86_STACK_ALIGNMENT_BYTES) {
+  if (RequiredStackAlignment > X86_STACK_ALIGNMENT_BYTES) {
     assert(IsEbpBasedFrame);
-    _and(getPhysicalRegister(getStackReg(), Traits::WordType),
+    _and(getPhysicalRegister(getStackReg(), WordType),
          Ctx->getConstantInt32(-RequiredStackAlignment));
   }
 
@@ -1085,7 +1030,7 @@
   // those that were register-allocated. Args are pushed right to left, so
   // Arg[0] is closest to the stack/frame pointer.
   RegNumT FrameOrStackReg = IsEbpBasedFrame ? getFrameReg() : getStackReg();
-  Variable *FramePtr = getPhysicalRegister(FrameOrStackReg, Traits::WordType);
+  Variable *FramePtr = getPhysicalRegister(FrameOrStackReg, WordType);
   size_t BasicFrameOffset = StackOffset;
   if (!IsEbpBasedFrame)
     BasicFrameOffset += SpillAreaSizeBytes;
@@ -1098,22 +1043,16 @@
     Variable *Arg = Args[i];
     // Skip arguments passed in registers.
     if (isVectorType(Arg->getType())) {
-      if (Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs))
+      if (RegX8632::getRegisterForXmmArgNum(
+              RegX8632::getArgIndex(i, NumXmmArgs))
               .hasValue()) {
         ++NumXmmArgs;
         continue;
       }
-    } else if (isScalarFloatingType(Arg->getType())) {
-      if (Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-          Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs))
-              .hasValue()) {
-        ++NumXmmArgs;
-        continue;
-      }
-    } else {
+    } else if (!isScalarFloatingType(Arg->getType())) {
       assert(isScalarIntegerType(Arg->getType()));
-      if (Traits::getRegisterForGprArgNum(Traits::WordType,
-                                          Traits::getArgIndex(i, NumGPRArgs))
+      if (RegX8632::getRegisterForGprArgNum(
+              WordType, RegX8632::getArgIndex(i, NumGPRArgs))
               .hasValue()) {
         ++NumGPRArgs;
         continue;
@@ -1159,7 +1098,7 @@
         GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes -
         maxOutArgsSizeBytes();
     Str << " in-args = " << InArgsSizeBytes << " bytes\n"
-        << " return address = " << Traits::X86_RET_IP_SIZE_BYTES << " bytes\n"
+        << " return address = " << X86_RET_IP_SIZE_BYTES << " bytes\n"
         << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n"
         << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n"
         << " globals spill area = " << GlobalsSize << " bytes\n"
@@ -1203,7 +1142,7 @@
   }
   Type Ty = Arg->getType();
   if (isVectorType(Ty)) {
-    InArgsSizeBytes = Traits::applyStackAlignment(InArgsSizeBytes);
+    InArgsSizeBytes = applyStackAlignment(InArgsSizeBytes);
   }
   Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes);
   InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
@@ -1257,7 +1196,7 @@
     const auto RegNum = RegNumT::fromInt(i);
     if (RegNum == getFrameReg() && IsEbpBasedFrame)
       continue;
-    const RegNumT Canonical = Traits::getBaseReg(RegNum);
+    const RegNumT Canonical = RegX8632::getBaseReg(RegNum);
     if (CalleeSaves[i] && RegsUsed[i]) {
       Popped[Canonical] = true;
     }
@@ -1266,12 +1205,12 @@
     if (!Popped[i])
       continue;
     const auto RegNum = RegNumT::fromInt(i);
-    assert(RegNum == Traits::getBaseReg(RegNum));
+    assert(RegNum == RegX8632::getBaseReg(RegNum));
     _pop_reg(RegNum);
   }
 }
 
-Type TargetX8632::stackSlotType() { return Traits::WordType; }
+Type TargetX8632::stackSlotType() { return WordType; }
 
 Operand *TargetX8632::loOperand(Operand *Operand) {
   assert(Operand->getType() == IceType_i64 ||
@@ -1337,7 +1276,7 @@
 
 SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include,
                                            RegSetMask Exclude) const {
-  return Traits::getRegisterSet(getFlags(), Include, Exclude);
+  return RegX8632::getRegisterSet(getFlags(), Include, Exclude);
 }
 
 void TargetX8632::lowerAlloca(const InstAlloca *Instr) {
@@ -1346,8 +1285,8 @@
   // alloca. All the alloca code ensures that the stack alignment is preserved
   // after the alloca. The stack alignment restriction can be relaxed in some
   // cases.
-  RequiredStackAlignment = std::max<size_t>(RequiredStackAlignment,
-                                            Traits::X86_STACK_ALIGNMENT_BYTES);
+  RequiredStackAlignment =
+      std::max<size_t>(RequiredStackAlignment, X86_STACK_ALIGNMENT_BYTES);
 
   // For default align=0, set it to the real value 1, to avoid any
   // bit-manipulation problems below.
@@ -1355,11 +1294,11 @@
 
   // LLVM enforces power of 2 alignment.
   assert(llvm::isPowerOf2_32(AlignmentParam));
-  assert(llvm::isPowerOf2_32(Traits::X86_STACK_ALIGNMENT_BYTES));
+  assert(llvm::isPowerOf2_32(X86_STACK_ALIGNMENT_BYTES));
 
   const uint32_t Alignment =
-      std::max(AlignmentParam, Traits::X86_STACK_ALIGNMENT_BYTES);
-  const bool OverAligned = Alignment > Traits::X86_STACK_ALIGNMENT_BYTES;
+      std::max(AlignmentParam, X86_STACK_ALIGNMENT_BYTES);
+  const bool OverAligned = Alignment > X86_STACK_ALIGNMENT_BYTES;
   const bool OptM1 = Func->getOptLevel() == Opt_m1;
   const bool AllocaWithKnownOffset = Instr->getKnownFrameOffset();
   const bool UseFramePointer =
@@ -1368,7 +1307,7 @@
   if (UseFramePointer)
     setHasFramePointer();
 
-  Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType);
+  Variable *esp = getPhysicalRegister(getStackReg(), WordType);
   if (OverAligned) {
     _and(esp, Ctx->getConstantInt32(-Alignment));
   }
@@ -1430,8 +1369,8 @@
     Variable *RegisterArg = nullptr;
     RegNumT RegNum;
     if (isVectorType(Ty)) {
-      RegNum =
-          Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs));
+      RegNum = RegX8632::getRegisterForXmmArgNum(
+          RegX8632::getArgIndex(i, NumXmmArgs));
       if (RegNum.hasNoValue()) {
         XmmSlotsRemain = false;
         continue;
@@ -1439,20 +1378,10 @@
       ++NumXmmArgs;
       RegisterArg = Func->makeVariable(Ty);
     } else if (isScalarFloatingType(Ty)) {
-      if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-        continue;
-      }
-      RegNum =
-          Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs));
-      if (RegNum.hasNoValue()) {
-        XmmSlotsRemain = false;
-        continue;
-      }
-      ++NumXmmArgs;
-      RegisterArg = Func->makeVariable(Ty);
+      continue;
     } else if (isScalarIntegerType(Ty)) {
-      RegNum = Traits::getRegisterForGprArgNum(
-          Ty, Traits::getArgIndex(i, NumGprArgs));
+      RegNum = RegX8632::getRegisterForGprArgNum(
+          Ty, RegX8632::getArgIndex(i, NumGprArgs));
       if (RegNum.hasNoValue()) {
         GprSlotsRemain = false;
         continue;
@@ -1559,7 +1488,7 @@
   constexpr uint32_t MaxOpsForOptimizedMul = 3;
   if (CountOps > MaxOpsForOptimizedMul)
     return false;
-  Variable *T = makeReg(Traits::WordType);
+  Variable *T = makeReg(WordType);
   if (typeWidthInBytes(Src0->getType()) < typeWidthInBytes(T->getType())) {
     Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
     _movzx(T, Src0RM);
@@ -1724,7 +1653,7 @@
     //   t1:ecx = c.lo & 0xff
     //   t2 = b.lo
     //   t3 = b.hi
-    T_1 = copyToReg8(Src1Lo, Traits::RegisterSet::Reg_cl);
+    T_1 = copyToReg8(Src1Lo, RegX8632::Reg_cl);
     _mov(T_2, Src0Lo);
     _mov(T_3, Src0Hi);
     switch (Op) {
@@ -1898,8 +1827,8 @@
       break;
     case InstArithmetic::Mul: {
       Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr;
-      Variable *T_4Lo = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
-      Variable *T_4Hi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
+      Variable *T_4Lo = makeReg(IceType_i32, RegX8632::Reg_eax);
+      Variable *T_4Hi = makeReg(IceType_i32, RegX8632::Reg_edx);
       // gcc does the following:
       // a=b*c ==>
       //   t1 = b.hi; t1 *=(imul) c.lo
@@ -1914,7 +1843,7 @@
       Src1Lo = legalize(Src1Lo, Legal_Reg | Legal_Mem);
       _mov(T_1, Src0Hi);
       _imul(T_1, Src1Lo);
-      _mov(T_3, Src0Lo, Traits::RegisterSet::Reg_eax);
+      _mov(T_3, Src0Lo, RegX8632::Reg_eax);
       _mul(T_4Lo, T_3, Src1Lo);
       // The mul instruction produces two dest variables, edx:eax. We create a
       // fake definition of edx to account for this.
@@ -2151,7 +2080,7 @@
     // The 8-bit version of imul only allows the form "imul r/m8" where T must
     // be in al.
     if (isByteSizedArithType(Ty)) {
-      _mov(T, Src0, Traits::RegisterSet::Reg_al);
+      _mov(T, Src0, RegX8632::Reg_al);
       Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
       _imul(T, Src0 == Src1 ? T : Src1);
       _mov(Dest, T);
@@ -2172,7 +2101,7 @@
     _mov(T, Src0);
     if (!llvm::isa<ConstantInteger32>(Src1) &&
         !llvm::isa<ConstantInteger64>(Src1))
-      Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
+      Src1 = copyToReg8(Src1, RegX8632::Reg_cl);
     _shl(T, Src1);
     _mov(Dest, T);
     break;
@@ -2180,7 +2109,7 @@
     _mov(T, Src0);
     if (!llvm::isa<ConstantInteger32>(Src1) &&
         !llvm::isa<ConstantInteger64>(Src1))
-      Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
+      Src1 = copyToReg8(Src1, RegX8632::Reg_cl);
     _shr(T, Src1);
     _mov(Dest, T);
     break;
@@ -2188,7 +2117,7 @@
     _mov(T, Src0);
     if (!llvm::isa<ConstantInteger32>(Src1) &&
         !llvm::isa<ConstantInteger64>(Src1))
-      Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
+      Src1 = copyToReg8(Src1, RegX8632::Reg_cl);
     _sar(T, Src1);
     _mov(Dest, T);
     break;
@@ -2201,21 +2130,17 @@
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for udiv");
-    case IceType_i64:
-      Eax = Traits::getRaxOrDie();
-      Edx = Traits::getRdxOrDie();
-      break;
     case IceType_i32:
-      Eax = Traits::RegisterSet::Reg_eax;
-      Edx = Traits::RegisterSet::Reg_edx;
+      Eax = RegX8632::Reg_eax;
+      Edx = RegX8632::Reg_edx;
       break;
     case IceType_i16:
-      Eax = Traits::RegisterSet::Reg_ax;
-      Edx = Traits::RegisterSet::Reg_dx;
+      Eax = RegX8632::Reg_ax;
+      Edx = RegX8632::Reg_dx;
       break;
     case IceType_i8:
-      Eax = Traits::RegisterSet::Reg_al;
-      Edx = Traits::RegisterSet::Reg_ah;
+      Eax = RegX8632::Reg_al;
+      Edx = RegX8632::Reg_ah;
       break;
     }
     T_edx = makeReg(Ty, Edx);
@@ -2243,7 +2168,7 @@
           //   add t,src
           //   sar t,log
           //   dest=t
-          uint32_t TypeWidth = Traits::X86_CHAR_BIT * typeWidthInBytes(Ty);
+          uint32_t TypeWidth = X86_CHAR_BIT * typeWidthInBytes(Ty);
           _mov(T, Src0);
           // If for some reason we are dividing by 1, just treat it like an
           // assignment.
@@ -2264,21 +2189,17 @@
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for sdiv");
-    case IceType_i64:
-      T_edx = makeReg(Ty, Traits::getRdxOrDie());
-      _mov(T, Src0, Traits::getRaxOrDie());
-      break;
     case IceType_i32:
-      T_edx = makeReg(Ty, Traits::RegisterSet::Reg_edx);
-      _mov(T, Src0, Traits::RegisterSet::Reg_eax);
+      T_edx = makeReg(Ty, RegX8632::Reg_edx);
+      _mov(T, Src0, RegX8632::Reg_eax);
       break;
     case IceType_i16:
-      T_edx = makeReg(Ty, Traits::RegisterSet::Reg_dx);
-      _mov(T, Src0, Traits::RegisterSet::Reg_ax);
+      T_edx = makeReg(Ty, RegX8632::Reg_dx);
+      _mov(T, Src0, RegX8632::Reg_ax);
       break;
     case IceType_i8:
-      T_edx = makeReg(IceType_i16, Traits::RegisterSet::Reg_ax);
-      _mov(T, Src0, Traits::RegisterSet::Reg_al);
+      T_edx = makeReg(IceType_i16, RegX8632::Reg_ax);
+      _mov(T, Src0, RegX8632::Reg_al);
       break;
     }
     _cbwdq(T_edx, T);
@@ -2293,21 +2214,17 @@
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for urem");
-    case IceType_i64:
-      Eax = Traits::getRaxOrDie();
-      Edx = Traits::getRdxOrDie();
-      break;
     case IceType_i32:
-      Eax = Traits::RegisterSet::Reg_eax;
-      Edx = Traits::RegisterSet::Reg_edx;
+      Eax = RegX8632::Reg_eax;
+      Edx = RegX8632::Reg_edx;
       break;
     case IceType_i16:
-      Eax = Traits::RegisterSet::Reg_ax;
-      Edx = Traits::RegisterSet::Reg_dx;
+      Eax = RegX8632::Reg_ax;
+      Edx = RegX8632::Reg_dx;
       break;
     case IceType_i8:
-      Eax = Traits::RegisterSet::Reg_al;
-      Edx = Traits::RegisterSet::Reg_ah;
+      Eax = RegX8632::Reg_al;
+      Edx = RegX8632::Reg_ah;
       break;
     }
     T_edx = makeReg(Ty, Edx);
@@ -2345,7 +2262,7 @@
           //   sub t,src
           //   neg t
           //   dest=t
-          uint32_t TypeWidth = Traits::X86_CHAR_BIT * typeWidthInBytes(Ty);
+          uint32_t TypeWidth = X86_CHAR_BIT * typeWidthInBytes(Ty);
           // If for some reason we are dividing by 1, just assign 0.
           if (LogDiv == 0) {
             _mov(Dest, Ctx->getConstantZero(Ty));
@@ -2371,21 +2288,17 @@
     switch (Ty) {
     default:
       llvm::report_fatal_error("Bad type for srem");
-    case IceType_i64:
-      Eax = Traits::getRaxOrDie();
-      Edx = Traits::getRdxOrDie();
-      break;
     case IceType_i32:
-      Eax = Traits::RegisterSet::Reg_eax;
-      Edx = Traits::RegisterSet::Reg_edx;
+      Eax = RegX8632::Reg_eax;
+      Edx = RegX8632::Reg_edx;
       break;
     case IceType_i16:
-      Eax = Traits::RegisterSet::Reg_ax;
-      Edx = Traits::RegisterSet::Reg_dx;
+      Eax = RegX8632::Reg_ax;
+      Edx = RegX8632::Reg_dx;
       break;
     case IceType_i8:
-      Eax = Traits::RegisterSet::Reg_al;
-      Edx = Traits::RegisterSet::Reg_ah;
+      Eax = RegX8632::Reg_al;
+      Edx = RegX8632::Reg_ah;
       break;
     }
     T_edx = makeReg(Ty, Edx);
@@ -2496,11 +2409,11 @@
   // This is compatible with the Microsoft x86-32 'cdecl' calling convention,
   // which doesn't have a 16-byte stack alignment requirement.
 
-  RequiredStackAlignment = std::max<size_t>(RequiredStackAlignment,
-                                            Traits::X86_STACK_ALIGNMENT_BYTES);
+  RequiredStackAlignment =
+      std::max<size_t>(RequiredStackAlignment, X86_STACK_ALIGNMENT_BYTES);
 
   constexpr SizeT MaxOperands =
-      constexprMax(Traits::X86_MAX_XMM_ARGS, Traits::X86_MAX_GPR_ARGS);
+      constexprMax(RegX8632::X86_MAX_XMM_ARGS, RegX8632::X86_MAX_GPR_ARGS);
   using OperandList = llvm::SmallVector<Operand *, MaxOperands>;
 
   OperandList XmmArgs;
@@ -2517,20 +2430,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(Traits::getArgIndex(i, XmmArgs.size()))
-            .hasValue()) {
-      XmmArgs.push_back(Arg);
-      XmmArgIndices.push_back(i);
-    } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-               Traits::getRegisterForXmmArgNum(
-                   Traits::getArgIndex(i, XmmArgs.size()))
-                   .hasValue()) {
+    if (isVectorType(Ty) && RegX8632::getRegisterForXmmArgNum(
+                                RegX8632::getArgIndex(i, XmmArgs.size()))
+                                .hasValue()) {
       XmmArgs.push_back(Arg);
       XmmArgIndices.push_back(i);
     } else if (isScalarIntegerType(Ty) &&
-               Traits::getRegisterForGprArgNum(
-                   Ty, Traits::getArgIndex(i, GprArgs.size()))
+               RegX8632::getRegisterForGprArgNum(
+                   Ty, RegX8632::getArgIndex(i, GprArgs.size()))
                    .hasValue()) {
       GprArgs.emplace_back(Ty, Arg);
       GprArgIndices.push_back(i);
@@ -2538,10 +2445,9 @@
       // Place on stack.
       StackArgs.push_back(Arg);
       if (isVectorType(Arg->getType())) {
-        ParameterAreaSizeBytes =
-            Traits::applyStackAlignment(ParameterAreaSizeBytes);
+        ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
       }
-      Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType);
+      Variable *esp = getPhysicalRegister(getStackReg(), WordType);
       Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes);
       StackArgLocations.push_back(X86OperandMem::create(Func, Ty, esp, Loc));
       ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
@@ -2550,16 +2456,14 @@
   // Ensure there is enough space for the fstp/movs for floating returns.
   Variable *Dest = Instr->getDest();
   const Type DestTy = Dest ? Dest->getType() : IceType_void;
-  if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-    if (isScalarFloatingType(DestTy)) {
-      ParameterAreaSizeBytes =
-          std::max(static_cast<size_t>(ParameterAreaSizeBytes),
-                   typeWidthInBytesOnStack(DestTy));
-    }
+  if (isScalarFloatingType(DestTy)) {
+    ParameterAreaSizeBytes =
+        std::max(static_cast<size_t>(ParameterAreaSizeBytes),
+                 typeWidthInBytesOnStack(DestTy));
   }
   // Adjust the parameter area so that the stack is aligned. It is assumed that
   // the stack is already aligned at the start of the calling sequence.
-  ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes);
+  ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
   assert(ParameterAreaSizeBytes <= maxOutArgsSizeBytes());
   // Copy arguments that are passed on the stack to the appropriate stack
   // locations.  We make sure legalize() is called on each argument at this
@@ -2571,8 +2475,8 @@
   // Copy arguments to be passed in registers to the appropriate registers.
   for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) {
     XmmArgs[i] = legalizeToReg(legalize(XmmArgs[i]),
-                               Traits::getRegisterForXmmArgNum(
-                                   Traits::getArgIndex(XmmArgIndices[i], i)));
+                               RegX8632::getRegisterForXmmArgNum(
+                                   RegX8632::getArgIndex(XmmArgIndices[i], i)));
   }
   // Materialize moves for arguments passed in GPRs.
   for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) {
@@ -2580,8 +2484,8 @@
     Operand *Arg =
         legalize(GprArgs[i].second, Legal_Default | Legal_Rematerializable);
     GprArgs[i].second = legalizeToReg(
-        Arg, Traits::getRegisterForGprArgNum(
-                 Arg->getType(), Traits::getArgIndex(GprArgIndices[i], i)));
+        Arg, RegX8632::getRegisterForGprArgNum(
+                 Arg->getType(), RegX8632::getArgIndex(GprArgIndices[i], i)));
     assert(SignatureTy == IceType_i64 || SignatureTy == IceType_i32);
     assert(SignatureTy == Arg->getType());
     (void)SignatureTy;
@@ -2610,19 +2514,17 @@
       llvm::report_fatal_error("Invalid Call dest type");
       break;
     case IceType_i32:
-      ReturnReg = makeReg(DestTy, Traits::RegisterSet::Reg_eax);
+      ReturnReg = makeReg(DestTy, RegX8632::Reg_eax);
       break;
     case IceType_i64:
-      ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
-      ReturnRegHi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
+      ReturnReg = makeReg(IceType_i32, RegX8632::Reg_eax);
+      ReturnRegHi = makeReg(IceType_i32, RegX8632::Reg_edx);
       break;
     case IceType_f32:
     case IceType_f64:
-      if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-        // Leave ReturnReg==ReturnRegHi==nullptr, and capture the result with
-        // the fstp instruction.
-        break;
-      }
+      // Leave ReturnReg==ReturnRegHi==nullptr, and capture the result with
+      // the fstp instruction.
+      break;
     // Fallthrough intended.
     case IceType_v4i1:
     case IceType_v8i1:
@@ -2631,7 +2533,7 @@
     case IceType_v8i16:
     case IceType_v4i32:
     case IceType_v4f32:
-      ReturnReg = makeReg(DestTy, Traits::RegisterSet::Reg_xmm0);
+      ReturnReg = makeReg(DestTy, RegX8632::Reg_xmm0);
       break;
     }
   }
@@ -2646,8 +2548,7 @@
   // Mark the call as killing all the caller-save registers.
   Context.insert<InstFakeKill>(NewCall);
   // Handle x86-32 floating point returns.
-  if (Dest != nullptr && isScalarFloatingType(DestTy) &&
-      !Traits::X86_PASS_SCALAR_FP_IN_XMM) {
+  if (Dest != nullptr && isScalarFloatingType(DestTy)) {
     // Special treatment for an FP function which returns its result in st(0).
     // If Dest ends up being a physical xmm register, the fstp emit code will
     // route st(0) through the space reserved in the function argument area
@@ -2672,13 +2573,7 @@
     Tmp = makeReg(DestTy);
     _movp(Tmp, ReturnReg);
     _movp(Dest, Tmp);
-  } else if (isScalarFloatingType(DestTy)) {
-    if (Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-      assert(ReturnReg && "FP type requires a return register");
-      _mov(Tmp, ReturnReg);
-      _mov(Dest, Tmp);
-    }
-  } else {
+  } else if (!isScalarFloatingType(DestTy)) {
     assert(isScalarIntegerType(DestTy));
     assert(ReturnReg && "Integer type requires a return register");
     if (DestTy == IceType_i64) {
@@ -2728,8 +2623,7 @@
       } else {
         /// width = width(elty) - 1; dest = (src << width) >> width
         SizeT ShiftAmount =
-            Traits::X86_CHAR_BIT * typeWidthInBytes(typeElementType(DestTy)) -
-            1;
+            X86_CHAR_BIT * typeWidthInBytes(typeElementType(DestTy)) - 1;
         Constant *ShiftConstant = Ctx->getConstantInt8(ShiftAmount);
         Variable *T = makeReg(DestTy);
         _movp(T, Src0RM);
@@ -2764,7 +2658,7 @@
       // shl t1, dst_bitwidth - 1
       // sar t1, dst_bitwidth - 1
       // dst = t1
-      size_t DestBits = Traits::X86_CHAR_BIT * typeWidthInBytes(DestTy);
+      size_t DestBits = X86_CHAR_BIT * typeWidthInBytes(DestTy);
       Constant *ShiftAmount = Ctx->getConstantInt32(DestBits - 1);
       Variable *T = makeReg(DestTy);
       if (typeWidthInBytes(DestTy) <= typeWidthInBytes(Src0RM->getType())) {
@@ -3102,7 +2996,7 @@
   unsigned Index = ElementIndex->getValue();
   Type Ty = SourceVectNotLegalized->getType();
   Type ElementTy = typeElementType(Ty);
-  Type InVectorElementTy = Traits::getInVectorElementType(Ty);
+  Type InVectorElementTy = InstX86Base::getInVectorElementType(Ty);
 
   // TODO(wala): Determine the best lowering sequences for each type.
   bool CanUsePextr = Ty == IceType_v8i16 || Ty == IceType_v8i1 ||
@@ -3217,11 +3111,11 @@
   //   ucomiss b, c       /* but swap b,c order if SwapOperands==true */
   //   setcc a, C1
   InstFcmp::FCond Condition = Fcmp->getCondition();
-  assert(static_cast<size_t>(Condition) < Traits::TableFcmpSize);
-  if (Traits::TableFcmp[Condition].SwapScalarOperands)
+  assert(static_cast<size_t>(Condition) < TableFcmpSize);
+  if (TableFcmp[Condition].SwapScalarOperands)
     std::swap(Src0, Src1);
-  const bool HasC1 = (Traits::TableFcmp[Condition].C1 != CondX86::Br_None);
-  const bool HasC2 = (Traits::TableFcmp[Condition].C2 != CondX86::Br_None);
+  const bool HasC1 = (TableFcmp[Condition].C1 != CondX86::Br_None);
+  const bool HasC2 = (TableFcmp[Condition].C2 != CondX86::Br_None);
   if (HasC1) {
     Src0 = legalize(Src0);
     Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
@@ -3229,20 +3123,20 @@
     _mov(T, Src0);
     _ucomiss(T, Src1RM);
     if (!HasC2) {
-      assert(Traits::TableFcmp[Condition].Default);
-      setccOrConsumer(Traits::TableFcmp[Condition].C1, Dest, Consumer);
+      assert(TableFcmp[Condition].Default);
+      setccOrConsumer(TableFcmp[Condition].C1, Dest, Consumer);
       return;
     }
   }
-  int32_t IntDefault = Traits::TableFcmp[Condition].Default;
+  int32_t IntDefault = TableFcmp[Condition].Default;
   if (Consumer == nullptr) {
     Constant *Default = Ctx->getConstantInt(Dest->getType(), IntDefault);
     _mov(Dest, Default);
     if (HasC1) {
       InstX86Label *Label = InstX86Label::create(Func, this);
-      _br(Traits::TableFcmp[Condition].C1, Label);
+      _br(TableFcmp[Condition].C1, Label);
       if (HasC2) {
-        _br(Traits::TableFcmp[Condition].C2, Label);
+        _br(TableFcmp[Condition].C2, Label);
       }
       Constant *NonDefault = Ctx->getConstantInt(Dest->getType(), !IntDefault);
       _redefined(_mov(Dest, NonDefault));
@@ -3256,9 +3150,9 @@
     if (IntDefault != 0)
       std::swap(TrueSucc, FalseSucc);
     if (HasC1) {
-      _br(Traits::TableFcmp[Condition].C1, FalseSucc);
+      _br(TableFcmp[Condition].C1, FalseSucc);
       if (HasC2) {
-        _br(Traits::TableFcmp[Condition].C2, FalseSucc);
+        _br(TableFcmp[Condition].C2, FalseSucc);
       }
       _br(TrueSucc);
       return;
@@ -3275,9 +3169,9 @@
     lowerMove(SelectDest, SrcF, false);
     if (HasC1) {
       InstX86Label *Label = InstX86Label::create(Func, this);
-      _br(Traits::TableFcmp[Condition].C1, Label);
+      _br(TableFcmp[Condition].C1, Label);
       if (HasC2) {
-        _br(Traits::TableFcmp[Condition].C2, Label);
+        _br(TableFcmp[Condition].C2, Label);
       }
       static constexpr bool IsRedefinition = true;
       lowerMove(SelectDest, SrcT, IsRedefinition);
@@ -3297,9 +3191,9 @@
     llvm::report_fatal_error("Expected vector compare");
 
   InstFcmp::FCond Condition = Fcmp->getCondition();
-  assert(static_cast<size_t>(Condition) < Traits::TableFcmpSize);
+  assert(static_cast<size_t>(Condition) < TableFcmpSize);
 
-  if (Traits::TableFcmp[Condition].SwapVectorOperands)
+  if (TableFcmp[Condition].SwapVectorOperands)
     std::swap(Src0, Src1);
 
   Variable *T = nullptr;
@@ -3317,7 +3211,7 @@
 
     switch (Condition) {
     default: {
-      const CmppsCond Predicate = Traits::TableFcmp[Condition].Predicate;
+      const CmppsCond Predicate = TableFcmp[Condition].Predicate;
       assert(Predicate != CondX86::Cmpps_Invalid);
       T = makeReg(Src0RM->getType());
       _movp(T, Src0RM);
@@ -3392,8 +3286,7 @@
   }
   Operand *Src0RM = legalizeSrc0ForCmp(Src0, Src1);
   _cmp(Src0RM, Src1);
-  setccOrConsumer(Traits::getIcmp32Mapping(Icmp->getCondition()), Dest,
-                  Consumer);
+  setccOrConsumer(getIcmp32Mapping(Icmp->getCondition()), Dest, Consumer);
 }
 
 void TargetX8632::lowerIcmpVector(const InstIcmp *Icmp) {
@@ -3517,7 +3410,7 @@
   Operand *Src1 = legalize(Icmp->getSrc(1));
   Variable *Dest = Icmp->getDest();
   InstIcmp::ICond Condition = Icmp->getCondition();
-  assert(static_cast<size_t>(Condition) < Traits::TableIcmp64Size);
+  assert(static_cast<size_t>(Condition) < TableIcmp64Size);
   Operand *Src0LoRM = nullptr;
   Operand *Src0HiRM = nullptr;
   // Legalize the portions of Src0 that are going to be needed.
@@ -3609,12 +3502,12 @@
     InstX86Label *LabelTrue = InstX86Label::create(Func, this);
     _mov(Dest, One);
     _cmp(Src0HiRM, Src1HiRI);
-    if (Traits::TableIcmp64[Condition].C1 != CondX86::Br_None)
-      _br(Traits::TableIcmp64[Condition].C1, LabelTrue);
-    if (Traits::TableIcmp64[Condition].C2 != CondX86::Br_None)
-      _br(Traits::TableIcmp64[Condition].C2, LabelFalse);
+    if (TableIcmp64[Condition].C1 != CondX86::Br_None)
+      _br(TableIcmp64[Condition].C1, LabelTrue);
+    if (TableIcmp64[Condition].C2 != CondX86::Br_None)
+      _br(TableIcmp64[Condition].C2, LabelFalse);
     _cmp(Src0LoRM, Src1LoRI);
-    _br(Traits::TableIcmp64[Condition].C3, LabelTrue);
+    _br(TableIcmp64[Condition].C3, LabelTrue);
     Context.insert(LabelFalse);
     _redefined(_mov(Dest, Zero));
     Context.insert(LabelTrue);
@@ -3622,13 +3515,12 @@
   }
   if (const auto *Br = llvm::dyn_cast<InstBr>(Consumer)) {
     _cmp(Src0HiRM, Src1HiRI);
-    if (Traits::TableIcmp64[Condition].C1 != CondX86::Br_None)
-      _br(Traits::TableIcmp64[Condition].C1, Br->getTargetTrue());
-    if (Traits::TableIcmp64[Condition].C2 != CondX86::Br_None)
-      _br(Traits::TableIcmp64[Condition].C2, Br->getTargetFalse());
+    if (TableIcmp64[Condition].C1 != CondX86::Br_None)
+      _br(TableIcmp64[Condition].C1, Br->getTargetTrue());
+    if (TableIcmp64[Condition].C2 != CondX86::Br_None)
+      _br(TableIcmp64[Condition].C2, Br->getTargetFalse());
     _cmp(Src0LoRM, Src1LoRI);
-    _br(Traits::TableIcmp64[Condition].C3, Br->getTargetTrue(),
-        Br->getTargetFalse());
+    _br(TableIcmp64[Condition].C3, Br->getTargetTrue(), Br->getTargetFalse());
     return;
   }
   if (auto *Select = llvm::dyn_cast<InstSelect>(Consumer)) {
@@ -3639,12 +3531,12 @@
     InstX86Label *LabelTrue = InstX86Label::create(Func, this);
     lowerMove(SelectDest, SrcT, false);
     _cmp(Src0HiRM, Src1HiRI);
-    if (Traits::TableIcmp64[Condition].C1 != CondX86::Br_None)
-      _br(Traits::TableIcmp64[Condition].C1, LabelTrue);
-    if (Traits::TableIcmp64[Condition].C2 != CondX86::Br_None)
-      _br(Traits::TableIcmp64[Condition].C2, LabelFalse);
+    if (TableIcmp64[Condition].C1 != CondX86::Br_None)
+      _br(TableIcmp64[Condition].C1, LabelTrue);
+    if (TableIcmp64[Condition].C2 != CondX86::Br_None)
+      _br(TableIcmp64[Condition].C2, LabelFalse);
     _cmp(Src0LoRM, Src1LoRI);
-    _br(Traits::TableIcmp64[Condition].C3, LabelTrue);
+    _br(TableIcmp64[Condition].C3, LabelTrue);
     Context.insert(LabelFalse);
     static constexpr bool IsRedefinition = true;
     lowerMove(SelectDest, SrcF, IsRedefinition);
@@ -3752,7 +3644,7 @@
 
   Type Ty = SourceVectNotLegalized->getType();
   Type ElementTy = typeElementType(Ty);
-  Type InVectorElementTy = Traits::getInVectorElementType(Ty);
+  Type InVectorElementTy = InstX86Base::getInVectorElementType(Ty);
 
   if (ElementTy == IceType_i1) {
     // Expand the element to the appropriate size for it to be inserted in the
@@ -4158,7 +4050,7 @@
   }
   case Intrinsics::Stacksave: {
     Variable *esp =
-        Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
+        Func->getTarget()->getPhysicalRegister(getStackReg(), WordType);
     Variable *Dest = Instr->getDest();
     _mov(Dest, esp);
     return;
@@ -4411,10 +4303,10 @@
   if (Ty == IceType_i64) {
     // Reserve the pre-colored registers first, before adding any more
     // infinite-weight variables from formMemoryOperand's legalization.
-    Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
-    Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
-    Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
-    Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx);
+    Variable *T_edx = makeReg(IceType_i32, RegX8632::Reg_edx);
+    Variable *T_eax = makeReg(IceType_i32, RegX8632::Reg_eax);
+    Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx);
+    Variable *T_ebx = makeReg(IceType_i32, RegX8632::Reg_ebx);
     _mov(T_eax, loOperand(Expected));
     _mov(T_edx, hiOperand(Expected));
     _mov(T_ebx, loOperand(Desired));
@@ -4432,17 +4324,14 @@
   switch (Ty) {
   default:
     llvm::report_fatal_error("Bad type for cmpxchg");
-  case IceType_i64:
-    Eax = Traits::getRaxOrDie();
-    break;
   case IceType_i32:
-    Eax = Traits::RegisterSet::Reg_eax;
+    Eax = RegX8632::Reg_eax;
     break;
   case IceType_i16:
-    Eax = Traits::RegisterSet::Reg_ax;
+    Eax = RegX8632::Reg_ax;
     break;
   case IceType_i8:
-    Eax = Traits::RegisterSet::Reg_al;
+    Eax = RegX8632::Reg_al;
     break;
   }
   Variable *T_eax = makeReg(Ty, Eax);
@@ -4641,13 +4530,13 @@
   Val = legalize(Val);
   Type Ty = Val->getType();
   if (Ty == IceType_i64) {
-    Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
-    Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
+    Variable *T_edx = makeReg(IceType_i32, RegX8632::Reg_edx);
+    Variable *T_eax = makeReg(IceType_i32, RegX8632::Reg_eax);
     X86OperandMem *Addr = formMemoryOperand(Ptr, Ty);
     _mov(T_eax, loOperand(Addr));
     _mov(T_edx, hiOperand(Addr));
-    Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
-    Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx);
+    Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx);
+    Variable *T_ebx = makeReg(IceType_i32, RegX8632::Reg_ebx);
     InstX86Label *Label = InstX86Label::create(Func, this);
     const bool IsXchg8b = Op_Lo == nullptr && Op_Hi == nullptr;
     if (!IsXchg8b) {
@@ -4695,17 +4584,14 @@
   switch (Ty) {
   default:
     llvm::report_fatal_error("Bad type for atomicRMW");
-  case IceType_i64:
-    Eax = Traits::getRaxOrDie();
-    break;
   case IceType_i32:
-    Eax = Traits::RegisterSet::Reg_eax;
+    Eax = RegX8632::Reg_eax;
     break;
   case IceType_i16:
-    Eax = Traits::RegisterSet::Reg_ax;
+    Eax = RegX8632::Reg_ax;
     break;
   case IceType_i8:
-    Eax = Traits::RegisterSet::Reg_al;
+    Eax = RegX8632::Reg_al;
     break;
   }
   Variable *T_eax = makeReg(Ty, Eax);
@@ -4882,7 +4768,7 @@
   const uint32_t CountValue = IsCountConst ? CountConst->getValue() : 0;
 
   if (shouldOptimizeMemIntrins() && IsCountConst &&
-      CountValue <= BytesPerStorep * Traits::MEMCPY_UNROLL_LIMIT) {
+      CountValue <= BytesPerStorep * MEMCPY_UNROLL_LIMIT) {
     // Unlikely, but nothing to do if it does happen
     if (CountValue == 0)
       return;
@@ -4934,7 +4820,7 @@
   const uint32_t CountValue = IsCountConst ? CountConst->getValue() : 0;
 
   if (shouldOptimizeMemIntrins() && IsCountConst &&
-      CountValue <= BytesPerStorep * Traits::MEMMOVE_UNROLL_LIMIT) {
+      CountValue <= BytesPerStorep * MEMMOVE_UNROLL_LIMIT) {
     // Unlikely, but nothing to do if it does happen
     if (CountValue == 0)
       return;
@@ -4942,8 +4828,7 @@
     Variable *SrcBase = legalizeToReg(Src);
     Variable *DestBase = legalizeToReg(Dest);
 
-    std::tuple<Type, Constant *, Variable *>
-        Moves[Traits::MEMMOVE_UNROLL_LIMIT];
+    std::tuple<Type, Constant *, Variable *> Moves[MEMMOVE_UNROLL_LIMIT];
     Constant *Offset;
     Variable *Reg;
 
@@ -4958,7 +4843,7 @@
     int32_t OffsetAmt = (CountValue & ~(TyWidth - 1)) - TyWidth;
     size_t N = 0;
     while (RemainingBytes >= TyWidth) {
-      assert(N <= Traits::MEMMOVE_UNROLL_LIMIT);
+      assert(N <= MEMMOVE_UNROLL_LIMIT);
       Offset = Ctx->getConstantInt32(OffsetAmt);
       Reg = makeReg(Ty);
       typedLoad(Ty, Reg, SrcBase, Offset);
@@ -4970,7 +4855,7 @@
     if (RemainingBytes != 0) {
       // Lower the remaining bytes. Adjust to larger types in order to make
       // use of overlaps in the copies.
-      assert(N <= Traits::MEMMOVE_UNROLL_LIMIT);
+      assert(N <= MEMMOVE_UNROLL_LIMIT);
       Ty = firstTypeThatFitsSize(RemainingBytes);
       Offset = Ctx->getConstantInt32(CountValue - typeWidthInBytes(Ty));
       Reg = makeReg(Ty);
@@ -5048,13 +4933,13 @@
     // on the memory unit as the access to the same memory are far apart.
     Type Ty = IceType_void;
     if (ValValue == 0 && CountValue >= BytesPerStoreq &&
-        CountValue <= BytesPerStorep * Traits::MEMSET_UNROLL_LIMIT) {
+        CountValue <= BytesPerStorep * MEMSET_UNROLL_LIMIT) {
       // When the value is zero it can be loaded into a vector register
       // cheaply using the xor trick.
       Base = legalizeToReg(Dest);
       VecReg = makeVectorOfZeros(IceType_v16i8);
       Ty = largestTypeInSize(CountValue);
-    } else if (CountValue <= BytesPerStorei32 * Traits::MEMSET_UNROLL_LIMIT) {
+    } else if (CountValue <= BytesPerStorei32 * MEMSET_UNROLL_LIMIT) {
       // When the value is non-zero or the count is small we can't use vector
       // instructions so are limited to 32-bit stores.
       Base = legalizeToReg(Dest);
@@ -6508,7 +6393,7 @@
     if (SrcTy == IceType_v4i1 || SrcTy == IceType_v4i32 ||
         SrcTy == IceType_v4f32) {
       Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem);
-      Variable *xmm0 = makeReg(IceType_v4i32, Traits::RegisterSet::Reg_xmm0);
+      Variable *xmm0 = makeReg(IceType_v4i32, RegX8632::Reg_xmm0);
       _movp(xmm0, ConditionRM);
       _psll(xmm0, Ctx->getConstantInt8(31));
       _movp(T, SrcFRM);
@@ -6518,7 +6403,7 @@
       assert(typeNumElements(SrcTy) == 8 || typeNumElements(SrcTy) == 16);
       Type SignExtTy =
           Condition->getType() == IceType_v8i1 ? IceType_v8i16 : IceType_v16i8;
-      Variable *xmm0 = makeReg(SignExtTy, Traits::RegisterSet::Reg_xmm0);
+      Variable *xmm0 = makeReg(SignExtTy, RegX8632::Reg_xmm0);
       lowerCast(InstCast::create(Func, InstCast::Sext, xmm0, Condition));
       _movp(T, SrcFRM);
       _pblendvb(T, SrcTRM, xmm0);
@@ -6526,7 +6411,7 @@
     }
     return;
   }
-  // Lower select without Traits::SSE4.1:
+  // Lower select without SSE4.1:
   // a=d?b:c ==>
   //   if elementtype(d) != i1:
   //      d=sext(d);
@@ -7192,7 +7077,7 @@
   } else {
     return;
   }
-  StackArgumentsSize = Traits::applyStackAlignment(StackArgumentsSize);
+  StackArgumentsSize = applyStackAlignment(StackArgumentsSize);
   updateMaxOutArgsSizeBytes(StackArgumentsSize);
 }
 
@@ -7207,24 +7092,18 @@
     // The PNaCl ABI requires the width of arguments to be at least 32 bits.
     assert(typeWidthInBytes(Ty) >= 4);
     if (isVectorType(Ty) &&
-        Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, XmmArgCount))
+        RegX8632::getRegisterForXmmArgNum(RegX8632::getArgIndex(i, XmmArgCount))
             .hasValue()) {
       ++XmmArgCount;
-    } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-               Traits::getRegisterForXmmArgNum(
-                   Traits::getArgIndex(i, XmmArgCount))
-                   .hasValue()) {
-      ++XmmArgCount;
     } else if (isScalarIntegerType(Ty) &&
-               Traits::getRegisterForGprArgNum(
-                   Ty, Traits::getArgIndex(i, GprArgCount))
+               RegX8632::getRegisterForGprArgNum(
+                   Ty, RegX8632::getArgIndex(i, GprArgCount))
                    .hasValue()) {
       // The 64 bit ABI allows some integers to be passed in GPRs.
       ++GprArgCount;
     } else {
       if (isVectorType(Ty)) {
-        OutArgumentsSizeBytes =
-            Traits::applyStackAlignment(OutArgumentsSizeBytes);
+        OutArgumentsSizeBytes = applyStackAlignment(OutArgumentsSizeBytes);
       }
       OutArgumentsSizeBytes += typeWidthInBytesOnStack(Ty);
     }
@@ -7321,8 +7200,7 @@
          Ty == IceType_v16i8);
   if (Ty == IceType_v4f32 || Ty == IceType_v4i32 || Ty == IceType_v8i16) {
     Variable *Reg = makeVectorOfOnes(Ty, RegNum);
-    SizeT Shift =
-        typeWidthInBytes(typeElementType(Ty)) * Traits::X86_CHAR_BIT - 1;
+    SizeT Shift = typeWidthInBytes(typeElementType(Ty)) * X86_CHAR_BIT - 1;
     _psll(Reg, Ctx->getConstantInt8(Shift));
     return Reg;
   } else {
@@ -7750,6 +7628,40 @@
   Str << "\n";
 }
 
+const TargetX8632::TableFcmpType TargetX8632::TableFcmp[] = {
+#define X(val, dflt, swapS, C1, C2, swapV, pred)                               \
+  {dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred},
+    FCMPX8632_TABLE
+#undef X
+};
+
+const size_t TargetX8632::TableFcmpSize = llvm::array_lengthof(TableFcmp);
+
+const TargetX8632::TableIcmp32Type TargetX8632::TableIcmp32[] = {
+#define X(val, C_32, C1_64, C2_64, C3_64) {CondX86::C_32},
+    ICMPX8632_TABLE
+#undef X
+};
+
+const size_t TargetX8632::TableIcmp32Size = llvm::array_lengthof(TableIcmp32);
+
+const TargetX8632::TableIcmp64Type TargetX8632::TableIcmp64[] = {
+#define X(val, C_32, C1_64, C2_64, C3_64)                                      \
+  {CondX86::C1_64, CondX86::C2_64, CondX86::C3_64},
+    ICMPX8632_TABLE
+#undef X
+};
+
+const size_t TargetX8632::TableIcmp64Size = llvm::array_lengthof(TableIcmp64);
+
+std::array<SmallBitVector, RCX86_NUM> TargetX8632::TypeToRegisterSet = {{}};
+
+std::array<SmallBitVector, RCX86_NUM> TargetX8632::TypeToRegisterSetUnfiltered =
+    {{}};
+
+std::array<SmallBitVector, RegisterSet::Reg_NUM> TargetX8632::RegisterAliases =
+    {{}};
+
 template <typename T>
 void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
   if (!BuildDefs::dump())
@@ -7866,69 +7778,6 @@
 }
 
 //------------------------------------------------------------------------------
-//      ______   ______     ______     __     ______   ______
-//     /\__  _\ /\  == \   /\  __ \   /\ \   /\__  _\ /\  ___\
-//     \/_/\ \/ \ \  __<   \ \  __ \  \ \ \  \/_/\ \/ \ \___  \
-//        \ \_\  \ \_\ \_\  \ \_\ \_\  \ \_\    \ \_\  \/\_____\
-//         \/_/   \/_/ /_/   \/_/\/_/   \/_/     \/_/   \/_____/
-//
-//------------------------------------------------------------------------------
-const TargetX8632Traits::TableFcmpType TargetX8632Traits::TableFcmp[] = {
-#define X(val, dflt, swapS, C1, C2, swapV, pred)                               \
-  {dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred},
-    FCMPX8632_TABLE
-#undef X
-};
-
-const size_t TargetX8632Traits::TableFcmpSize = llvm::array_lengthof(TableFcmp);
-
-const TargetX8632Traits::TableIcmp32Type TargetX8632Traits::TableIcmp32[] = {
-#define X(val, C_32, C1_64, C2_64, C3_64) {CondX86::C_32},
-    ICMPX8632_TABLE
-#undef X
-};
-
-const size_t TargetX8632Traits::TableIcmp32Size =
-    llvm::array_lengthof(TableIcmp32);
-
-const TargetX8632Traits::TableIcmp64Type TargetX8632Traits::TableIcmp64[] = {
-#define X(val, C_32, C1_64, C2_64, C3_64)                                      \
-  {CondX86::C1_64, CondX86::C2_64, CondX86::C3_64},
-    ICMPX8632_TABLE
-#undef X
-};
-
-const size_t TargetX8632Traits::TableIcmp64Size =
-    llvm::array_lengthof(TableIcmp64);
-
-const TargetX8632Traits::TableTypeX8632AttributesType
-    TargetX8632Traits::TableTypeX8632Attributes[] = {
-#define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld)    \
-  {IceType_##elty},
-        ICETYPEX86_TABLE
-#undef X
-};
-
-const size_t TargetX8632Traits::TableTypeX8632AttributesSize =
-    llvm::array_lengthof(TableTypeX8632Attributes);
-
-#if defined(_WIN32)
-// Windows 32-bit only guarantees 4 byte stack alignment
-const uint32_t TargetX8632Traits::X86_STACK_ALIGNMENT_BYTES = 4;
-#else
-const uint32_t TargetX8632Traits::X86_STACK_ALIGNMENT_BYTES = 16;
-#endif
-const char *TargetX8632Traits::TargetName = "X8632";
-
-std::array<SmallBitVector, RCX86_NUM> TargetX8632::TypeToRegisterSet = {{}};
-
-std::array<SmallBitVector, RCX86_NUM> TargetX8632::TypeToRegisterSetUnfiltered =
-    {{}};
-
-std::array<SmallBitVector, RegisterSet::Reg_NUM> TargetX8632::RegisterAliases =
-    {{}};
-
-//------------------------------------------------------------------------------
 //     __      ______  __     __  ______  ______  __  __   __  ______
 //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
 //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
@@ -7937,17 +7786,17 @@
 //
 //------------------------------------------------------------------------------
 void TargetX8632::_add_sp(Operand *Adjustment) {
-  Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
+  Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
   _add(esp, Adjustment);
 }
 
 void TargetX8632::_mov_sp(Operand *NewValue) {
-  Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
+  Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
   _redefined(_mov(esp, NewValue));
 }
 
 void TargetX8632::_sub_sp(Operand *Adjustment) {
-  Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
+  Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
   _sub(esp, Adjustment);
   // Add a fake use of the stack pointer, to prevent the stack pointer
   // adustment from being dead-code eliminated in a function that doesn't
@@ -7956,8 +7805,8 @@
 }
 
 void TargetX8632::_link_bp() {
-  Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
-  Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
+  Variable *ebp = getPhysicalRegister(RegX8632::Reg_ebp);
+  Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
   _push(ebp);
   _mov(ebp, esp);
   // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode).
@@ -7965,8 +7814,8 @@
 }
 
 void TargetX8632::_unlink_bp() {
-  Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
-  Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
+  Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
+  Variable *ebp = getPhysicalRegister(RegX8632::Reg_ebp);
   // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake
   // use of esp before the assignment of esp=ebp keeps previous esp
   // adjustments from being dead-code eliminated.
@@ -7976,11 +7825,11 @@
 }
 
 void TargetX8632::_push_reg(RegNumT RegNum) {
-  _push(getPhysicalRegister(RegNum, Traits::WordType));
+  _push(getPhysicalRegister(RegNum, WordType));
 }
 
 void TargetX8632::_pop_reg(RegNumT RegNum) {
-  _pop(getPhysicalRegister(RegNum, Traits::WordType));
+  _pop(getPhysicalRegister(RegNum, WordType));
 }
 
 /// Lower an indirect jump adding sandboxing when needed.
@@ -7999,22 +7848,20 @@
 Variable *TargetX8632::moveReturnValueToRegister(Operand *Value,
                                                  Type ReturnType) {
   if (isVectorType(ReturnType)) {
-    return legalizeToReg(Value, Traits::RegisterSet::Reg_xmm0);
+    return legalizeToReg(Value, RegX8632::Reg_xmm0);
   } else if (isScalarFloatingType(ReturnType)) {
     _fld(Value);
     return nullptr;
   } else {
     assert(ReturnType == IceType_i32 || ReturnType == IceType_i64);
     if (ReturnType == IceType_i64) {
-      Variable *eax =
-          legalizeToReg(loOperand(Value), Traits::RegisterSet::Reg_eax);
-      Variable *edx =
-          legalizeToReg(hiOperand(Value), Traits::RegisterSet::Reg_edx);
+      Variable *eax = legalizeToReg(loOperand(Value), RegX8632::Reg_eax);
+      Variable *edx = legalizeToReg(hiOperand(Value), RegX8632::Reg_edx);
       Context.insert<InstFakeUse>(edx);
       return eax;
     } else {
       Variable *Reg = nullptr;
-      _mov(Reg, Value, Traits::RegisterSet::Reg_eax);
+      _mov(Reg, Value, RegX8632::Reg_eax);
       return Reg;
     }
   }
@@ -8027,9 +7874,9 @@
     // stack amount specified in EAX, so we save ESP in ECX, and restore them
     // both after the call.
 
-    Variable *EAX = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
-    Variable *ESP = makeReg(IceType_i32, Traits::RegisterSet::Reg_esp);
-    Variable *ECX = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
+    Variable *EAX = makeReg(IceType_i32, RegX8632::Reg_eax);
+    Variable *ESP = makeReg(IceType_i32, RegX8632::Reg_esp);
+    Variable *ECX = makeReg(IceType_i32, RegX8632::Reg_ecx);
 
     _push_reg(ECX->getRegNum());
     _mov(ECX, ESP);
diff --git a/third_party/subzero/src/IceTargetLoweringX8632.h b/third_party/subzero/src/IceTargetLoweringX8632.h
index b747ca2..69e6694 100644
--- a/third_party/subzero/src/IceTargetLoweringX8632.h
+++ b/third_party/subzero/src/IceTargetLoweringX8632.h
@@ -23,7 +23,6 @@
 #include "IceRegistersX8632.h"
 #include "IceSwitchLowering.h"
 #include "IceTargetLoweringX86.h"
-#include "IceTargetLoweringX8632Traits.h"
 #include "IceTargetLoweringX86RegClass.h"
 #include "IceUtils.h"
 
@@ -36,6 +35,8 @@
 
 using namespace ::Ice::X86;
 
+constexpr Type WordType = IceType_i32;
+
 class BoolFoldingEntry {
   BoolFoldingEntry(const BoolFoldingEntry &) = delete;
 
@@ -103,22 +104,13 @@
   CfgUnorderedMap<SizeT, BoolFoldingEntry> Producers;
 };
 
-/// TargetX8632 is a template for all X86 Targets, and it relies on the CRT
-/// pattern for generating code, delegating to actual backends target-specific
-/// lowerings (e.g., call, ret, and intrinsics.)
-///
-/// Note: Ideally, we should be able to
-///
-///  static_assert(std::is_base_of<TargetX8632<TraitsType>,
-///  Machine>::value);
-///
-/// but that does not work: the compiler does not know that Machine inherits
-/// from TargetX8632 at this point in translation.
 class TargetX8632 : public TargetX86 {
   TargetX8632() = delete;
   TargetX8632(const TargetX8632 &) = delete;
   TargetX8632 &operator=(const TargetX8632 &) = delete;
 
+  friend class BoolFolding;
+
 public:
   using BrCond = CondX86::BrCond;
   using CmppsCond = CondX86::CmppsCond;
@@ -140,9 +132,7 @@
   void doLoadOpt();
   bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
 
-  SizeT getNumRegisters() const override {
-    return Traits::RegisterSet::Reg_NUM;
-  }
+  SizeT getNumRegisters() const override { return RegisterSet::Reg_NUM; }
 
   Inst *createLoweredMove(Variable *Dest, Variable *SrcVar) override {
     if (isVectorType(Dest->getType())) {
@@ -210,16 +200,16 @@
   }
   size_t typeWidthInBytesOnStack(Type Ty) const override {
     // Round up to the next multiple of WordType bytes.
-    const uint32_t WordSizeInBytes = typeWidthInBytes(Traits::WordType);
+    const uint32_t WordSizeInBytes = typeWidthInBytes(WordType);
     return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes);
   }
   uint32_t getStackAlignment() const override {
-    return Traits::X86_STACK_ALIGNMENT_BYTES;
+    return X86_STACK_ALIGNMENT_BYTES;
   }
   bool needsStackPointerAlignment() const override {
     // If the ABI's stack alignment is smaller than the vector size (16 bytes),
     // use the (realigned) stack pointer for addressing any stack variables.
-    return Traits::X86_STACK_ALIGNMENT_BYTES < 16;
+    return X86_STACK_ALIGNMENT_BYTES < 16;
   }
   void reserveFixedAllocaArea(size_t Size, size_t Align) override {
     FixedAllocaSizeBytes = Size;
@@ -381,7 +371,7 @@
   /// function. Otherwise some esp adjustments get dead-code eliminated.
   void keepEspLiveAtExit() {
     Variable *esp =
-        Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
+        Func->getTarget()->getPhysicalRegister(getStackReg(), WordType);
     Context.insert<InstFakeUse>(esp);
   }
 
@@ -496,7 +486,7 @@
     Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
   }
   void _br(BrCond Condition, InstX86Label *Label,
-           typename InstX86Br::Mode Kind = InstX86Br::Near) {
+           InstX86Br::Mode Kind = InstX86Br::Near) {
     Context.insert<InstX86Br>(Label, Condition, Kind);
   }
   void _bsf(Variable *Dest, Operand *Src0) {
@@ -863,8 +853,19 @@
   bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
   void findRMW();
 
+  static uint32_t applyStackAlignment(uint32_t Value);
+
   bool IsEbpBasedFrame = false;
-  size_t RequiredStackAlignment = sizeof(int32_t); // 4 bytes
+
+#if defined(_WIN32)
+  // Windows 32-bit only guarantees 4 byte stack alignment
+  static constexpr uint32_t X86_STACK_ALIGNMENT_BYTES = 4;
+#else
+  /// Stack alignment guaranteed by the System V ABI.
+  static constexpr uint32_t X86_STACK_ALIGNMENT_BYTES = 16;
+#endif
+  /// Stack alignment required by the currently lowered function.
+  size_t RequiredStackAlignment = X86_STACK_ALIGNMENT_BYTES;
   size_t SpillAreaSizeBytes = 0;
   size_t FixedAllocaSizeBytes = 0;
   size_t FixedAllocaAlignBytes = 0;
@@ -872,8 +873,7 @@
   uint32_t MaxOutArgsSizeBytes = 0;
   static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet;
   static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered;
-  static std::array<SmallBitVector, Traits::RegisterSet::Reg_NUM>
-      RegisterAliases;
+  static std::array<SmallBitVector, RegisterSet::Reg_NUM> RegisterAliases;
   SmallBitVector RegsUsed;
   std::array<VarList, IceType_NUM> PhysicalRegisters;
   // RebasePtr is a Variable that holds the Rebasing pointer (if any) for the
@@ -951,6 +951,60 @@
                                       int8_t Idx14, int8_t Idx15);
   /// @}
 
+  /// The following table summarizes the logic for lowering the fcmp
+  /// instruction. There is one table entry for each of the 16 conditions.
+  ///
+  /// The first four columns describe the case when the operands are floating
+  /// point scalar values. A comment in lowerFcmp() describes the lowering
+  /// template. In the most general case, there is a compare followed by two
+  /// conditional branches, because some fcmp conditions don't map to a single
+  /// x86 conditional branch. However, in many cases it is possible to swap the
+  /// operands in the comparison and have a single conditional branch. Since
+  /// it's quite tedious to validate the table by hand, good execution tests are
+  /// helpful.
+  ///
+  /// The last two columns describe the case when the operands are vectors of
+  /// floating point values. For most fcmp conditions, there is a clear mapping
+  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
+  /// special code to handle and these are marked in the table with a
+  /// Cmpps_Invalid predicate.
+  /// {@
+  static const struct TableFcmpType {
+    uint32_t Default;
+    bool SwapScalarOperands;
+    CondX86::BrCond C1, C2;
+    bool SwapVectorOperands;
+    CondX86::CmppsCond Predicate;
+  } TableFcmp[];
+  static const size_t TableFcmpSize;
+  /// @}
+
+  /// The following table summarizes the logic for lowering the icmp instruction
+  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
+  /// x86 conditional branch instruction.
+  /// {@
+  static const struct TableIcmp32Type {
+    CondX86::BrCond Mapping;
+  } TableIcmp32[];
+  static const size_t TableIcmp32Size;
+  /// @}
+
+  /// The following table summarizes the logic for lowering the icmp instruction
+  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
+  /// conditional branches are needed. For the other conditions, three separate
+  /// conditional branches are needed.
+  /// {@
+  static const struct TableIcmp64Type {
+    CondX86::BrCond C1, C2, C3;
+  } TableIcmp64[];
+  static const size_t TableIcmp64Size;
+  /// @}
+
+  static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
+    assert(static_cast<size_t>(Cond) < TableIcmp32Size);
+    return TableIcmp32[Cond].Mapping;
+  }
+
 public:
   static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
     return makeUnique<TargetX8632>(Func);
@@ -967,7 +1021,6 @@
 };
 
 class TargetDataX8632 final : public TargetDataLowering {
-  using Traits = TargetX8632Traits;
   TargetDataX8632() = delete;
   TargetDataX8632(const TargetDataX8632 &) = delete;
   TargetDataX8632 &operator=(const TargetDataX8632 &) = delete;
diff --git a/third_party/subzero/src/IceTargetLoweringX8632Traits.h b/third_party/subzero/src/IceTargetLoweringX8632Traits.h
deleted file mode 100644
index 019a70c..0000000
--- a/third_party/subzero/src/IceTargetLoweringX8632Traits.h
+++ /dev/null
@@ -1,519 +0,0 @@
-//===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=//
-//
-//                        The Subzero Code Generator
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Declares the X8632 Target Lowering Traits.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
-#define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
-
-#include "IceAssembler.h"
-#include "IceConditionCodesX86.h"
-#include "IceDefs.h"
-#include "IceInst.h"
-#include "IceOperand.h"
-#include "IceRegistersX8632.h"
-#include "IceTargetLowering.h"
-#include "IceTargetLoweringX8632.def"
-#include "IceTargetLoweringX86RegClass.h"
-
-#include <array>
-
-namespace Ice {
-namespace X8632 {
-using namespace ::Ice::X86;
-
-struct Insts;
-class TargetX8632;
-class AssemblerX8632;
-class TargetX8632;
-
-struct TargetX8632Traits {
-  using RegisterSet = ::Ice::RegX8632;
-  using GPRRegister = RegisterSet::GPRRegister;
-  using ByteRegister = RegisterSet::ByteRegister;
-  using XmmRegister = RegisterSet::XmmRegister;
-  using X87STRegister = RegisterSet::X87STRegister;
-
-  //----------------------------------------------------------------------------
-  //     __      ______  __     __  ______  ______  __  __   __  ______
-  //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
-  //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
-  //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
-  //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
-  //
-  //----------------------------------------------------------------------------
-  static const char *TargetName;
-  static constexpr Type WordType = IceType_i32;
-
-  static const char *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,      \
-          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
-  name,
-        REGX8632_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    return RegNames[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,      \
-          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
-  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
-        REGX8632_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
-    return GPRRegs[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,      \
-          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
-  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
-        REGX8632_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
-    return ByteRegs[RegNum];
-  }
-
-  static bool isXmm(RegNumT RegNum) {
-    static const bool IsXmm[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)                                     \
-  isXmm,
-        REGX8632_TABLE
-#undef X
-    };
-    return IsXmm[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,      \
-          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
-  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
-        REGX8632_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
-    return XmmRegs[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,      \
-          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
-  encode,
-        REGX8632_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    return Encoding[RegNum];
-  }
-
-  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)                                     \
-  RegisterSet::base,
-        REGX8632_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    return BaseRegs[RegNum];
-  }
-
-private:
-  static RegisterSet::AllRegisters getFirstGprForType(Type Ty) {
-    switch (Ty) {
-    default:
-      llvm_unreachable("Invalid type for GPR.");
-    case IceType_i1:
-    case IceType_i8:
-      return RegisterSet::Reg_al;
-    case IceType_i16:
-      return RegisterSet::Reg_ax;
-    case IceType_i32:
-      return RegisterSet::Reg_eax;
-    }
-  }
-
-public:
-  // Return a register in RegNum's alias set that is suitable for Ty.
-  static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
-    assert(RegNum.hasValue());
-
-    if (!isScalarIntegerType(Ty)) {
-      return RegNum;
-    }
-
-    // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions.
-    switch (RegNum) {
-    default:
-      break;
-    case RegisterSet::Reg_ah:
-    case RegisterSet::Reg_bh:
-    case RegisterSet::Reg_ch:
-    case RegisterSet::Reg_dh:
-      assert(isByteSizedType(Ty));
-      return RegNum;
-    }
-
-    const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty);
-
-    switch (RegNum) {
-    default:
-      llvm::report_fatal_error("Unknown register.");
-#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
-          isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
-          isTrunc8Rcvr, isAhRcvr, aliases)                                     \
-  case RegisterSet::val: {                                                     \
-    if (!isGPR)                                                                \
-      return RegisterSet::val;                                                 \
-    assert((is32) || (is16) || (is8) ||                                        \
-           getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp);              \
-    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 RegNumT NewRegNum =                                                  \
-        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
-    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
-           "Error involving " #val);                                           \
-    return NewRegNum;                                                          \
-  }
-      REGX8632_TABLE
-#undef X
-    }
-  }
-
-private:
-  /// SizeOf is used to obtain the size of an initializer list as a constexpr
-  /// expression. This is only needed until our C++ library is updated to
-  /// C++ 14 -- which defines constexpr members to std::initializer_list.
-  class SizeOf {
-    SizeOf(const SizeOf &) = delete;
-    SizeOf &operator=(const SizeOf &) = delete;
-
-  public:
-    constexpr SizeOf() : Size(0) {}
-    template <typename... T>
-    explicit constexpr SizeOf(T...) : Size(__length<T...>::value) {}
-    constexpr SizeT size() const { return Size; }
-
-  private:
-    template <typename T, typename... U> struct __length {
-      static constexpr std::size_t value = 1 + __length<U...>::value;
-    };
-
-    template <typename T> struct __length<T> {
-      static constexpr std::size_t value = 1;
-    };
-
-    const std::size_t Size;
-  };
-
-public:
-  static void initRegisterSet(
-      const ::Ice::ClFlags & /*Flags*/,
-      std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
-      std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
-    SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
-    SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
-    SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
-    SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
-
-    static constexpr struct {
-      uint16_t Val;
-      unsigned Is64 : 1;
-      unsigned Is32 : 1;
-      unsigned Is16 : 1;
-      unsigned Is8 : 1;
-      unsigned IsXmm : 1;
-      unsigned Is64To8 : 1;
-      unsigned Is32To8 : 1;
-      unsigned Is16To8 : 1;
-      unsigned IsTrunc8Rcvr : 1;
-      unsigned IsAhRcvr : 1;
-#define NUM_ALIASES_BITS 2
-      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
-      uint16_t Aliases[1 << NUM_ALIASES_BITS];
-#undef NUM_ALIASES_BITS
-    } X8632RegTable[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)                                     \
-  {                                                                            \
-      RegisterSet::val,                                                        \
-      is64,                                                                    \
-      is32,                                                                    \
-      is16,                                                                    \
-      is8,                                                                     \
-      isXmm,                                                                   \
-      is64To8,                                                                 \
-      is32To8,                                                                 \
-      is16To8,                                                                 \
-      isTrunc8Rcvr,                                                            \
-      isAhRcvr,                                                                \
-      (SizeOf aliases).size(),                                                 \
-      aliases,                                                                 \
-  },
-        REGX8632_TABLE
-#undef X
-    };
-
-    for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) {
-      const auto &Entry = X8632RegTable[ii];
-      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
-      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
-      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
-      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
-      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
-      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
-      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
-      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
-      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
-      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
-      (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
-      for (SizeT J = 0; J < Entry.NumAliases; J++) {
-        SizeT Alias = Entry.Aliases[J];
-        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
-        (*RegisterAliases)[Entry.Val].set(Alias);
-      }
-      (*RegisterAliases)[Entry.Val].set(Entry.Val);
-    }
-
-    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
-    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
-    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
-    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
-    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
-    (*TypeToRegisterSet)[RC_i64] = InvalidRegisters;
-    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
-    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
-    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
-    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
-    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
-    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
-    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
-    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
-  }
-
-  static SmallBitVector getRegisterSet(const ::Ice::ClFlags & /*Flags*/,
-                                       TargetLowering::RegSetMask Include,
-                                       TargetLowering::RegSetMask Exclude) {
-    SmallBitVector Registers(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)                                     \
-  if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
-    Registers[RegisterSet::val] = true;                                        \
-  if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
-    Registers[RegisterSet::val] = true;                                        \
-  if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
-    Registers[RegisterSet::val] = true;                                        \
-  if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
-    Registers[RegisterSet::val] = true;                                        \
-  if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
-    Registers[RegisterSet::val] = false;                                       \
-  if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
-    Registers[RegisterSet::val] = false;                                       \
-  if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
-    Registers[RegisterSet::val] = false;                                       \
-  if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
-    Registers[RegisterSet::val] = false;
-
-    REGX8632_TABLE
-
-#undef X
-
-    return Registers;
-  }
-
-  static RegNumT getRaxOrDie() {
-    llvm::report_fatal_error("no rax in non-64-bit mode.");
-  }
-
-  static RegNumT getRdxOrDie() {
-    llvm::report_fatal_error("no rdx in non-64-bit mode.");
-  }
-
-  // x86-32 calling convention:
-  //
-  // * The first four arguments of vector type, regardless of their position
-  // relative to the other arguments in the argument list, are placed in
-  // registers xmm0 - xmm3.
-  //
-  // This intends to match the section "IA-32 Function Calling Convention" of
-  // the document "OS X ABI Function Call Guide" by Apple.
-
-  /// The maximum number of arguments to pass in XMM registers
-  static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
-  /// The maximum number of arguments to pass in GPR registers
-  static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
-  /// 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 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 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) {
-    assert(Ty == IceType_i64 || Ty == IceType_i32);
-    (void)Ty;
-    (void)ArgNum;
-    return RegNumT();
-  }
-  // Given the absolute argument position and argument position by type, return
-  // the register index to assign it to.
-  static SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
-    (void)argPos;
-    return argPosByType;
-  };
-
-  /// The number of bits in a byte
-  static constexpr uint32_t X86_CHAR_BIT = 8;
-  /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
-  /// is used as an argument to std::max(), and the default std::less<T> has an
-  /// operator(T const&, T const&) which requires this member to have an
-  /// address.
-  static const uint32_t X86_STACK_ALIGNMENT_BYTES;
-  /// Size of the return address on the stack
-  static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4;
-  /// The number of different NOP instructions
-  static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
-
-  /// \name Limits for unrolling memory intrinsics.
-  /// @{
-  static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
-  static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
-  static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
-  /// @}
-
-  /// Value is in bytes. Return Value adjusted to the next highest multiple of
-  /// the stack alignment.
-  static uint32_t applyStackAlignment(uint32_t Value) {
-    return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
-  }
-
-  /// Return the type which the elements of the vector have in the X86
-  /// representation of the vector.
-  static Type getInVectorElementType(Type Ty) {
-    assert(isVectorType(Ty));
-    assert(static_cast<size_t>(Ty) < TableTypeX8632AttributesSize);
-    return TableTypeX8632Attributes[Ty].InVectorElementType;
-  }
-
-  // Note: The following data structures are defined in
-  // IceTargetLoweringX8632.cpp.
-
-  /// The following table summarizes the logic for lowering the fcmp
-  /// instruction. There is one table entry for each of the 16 conditions.
-  ///
-  /// The first four columns describe the case when the operands are floating
-  /// point scalar values. A comment in lowerFcmp() describes the lowering
-  /// template. In the most general case, there is a compare followed by two
-  /// conditional branches, because some fcmp conditions don't map to a single
-  /// x86 conditional branch. However, in many cases it is possible to swap the
-  /// operands in the comparison and have a single conditional branch. Since
-  /// it's quite tedious to validate the table by hand, good execution tests are
-  /// helpful.
-  ///
-  /// The last two columns describe the case when the operands are vectors of
-  /// floating point values. For most fcmp conditions, there is a clear mapping
-  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
-  /// special code to handle and these are marked in the table with a
-  /// Cmpps_Invalid predicate.
-  /// {@
-  static const struct TableFcmpType {
-    uint32_t Default;
-    bool SwapScalarOperands;
-    CondX86::BrCond C1, C2;
-    bool SwapVectorOperands;
-    CondX86::CmppsCond Predicate;
-  } TableFcmp[];
-  static const size_t TableFcmpSize;
-  /// @}
-
-  /// The following table summarizes the logic for lowering the icmp instruction
-  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
-  /// x86 conditional branch instruction.
-  /// {@
-  static const struct TableIcmp32Type {
-    CondX86::BrCond Mapping;
-  } TableIcmp32[];
-  static const size_t TableIcmp32Size;
-  /// @}
-
-  /// The following table summarizes the logic for lowering the icmp instruction
-  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
-  /// conditional branches are needed. For the other conditions, three separate
-  /// conditional branches are needed.
-  /// {@
-  static const struct TableIcmp64Type {
-    CondX86::BrCond C1, C2, C3;
-  } TableIcmp64[];
-  static const size_t TableIcmp64Size;
-  /// @}
-
-  static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
-    assert(static_cast<size_t>(Cond) < TableIcmp32Size);
-    return TableIcmp32[Cond].Mapping;
-  }
-
-  static const struct TableTypeX8632AttributesType {
-    Type InVectorElementType;
-  } TableTypeX8632Attributes[];
-  static const size_t TableTypeX8632AttributesSize;
-};
-
-} // end of namespace X8632
-} // end of namespace Ice
-
-#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
diff --git a/third_party/subzero/src/IceTargetLoweringX8664.cpp b/third_party/subzero/src/IceTargetLoweringX8664.cpp
index 37c8d2a..13f8f85 100644
--- a/third_party/subzero/src/IceTargetLoweringX8664.cpp
+++ b/third_party/subzero/src/IceTargetLoweringX8664.cpp
@@ -25,7 +25,7 @@
 #include "IceLiveness.h"
 #include "IceOperand.h"
 #include "IcePhiLoweringImpl.h"
-#include "IceTargetLoweringX8664Traits.h"
+#include "IceTargetLoweringX8664.def"
 #include "IceUtils.h"
 #include "IceVariableSplitting.h"
 
@@ -65,91 +65,29 @@
   return ::Ice::X8664::TargetX8664::getPointerType();
 }
 
-} // end of namespace X8664
+} // namespace X8664
 
 namespace Ice {
 namespace X8664 {
 
-template <typename T> struct PoolTypeConverter {};
+/// The number of bits in a byte
+static constexpr uint32_t X86_CHAR_BIT = 8;
+/// Size of the return address on the stack
+static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8;
 
-template <> struct PoolTypeConverter<float> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantFloat;
-  static const Type Ty = IceType_f32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-template <> struct PoolTypeConverter<double> {
-  using PrimitiveIntType = uint64_t;
-  using IceType = ConstantDouble;
-  static const Type Ty = IceType_f64;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint32_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint16_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i16;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint8_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i8;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-
-const char *PoolTypeConverter<float>::TypeName = "float";
-const char *PoolTypeConverter<float>::AsmTag = ".long";
-const char *PoolTypeConverter<float>::PrintfString = "0x%x";
-
-const char *PoolTypeConverter<double>::TypeName = "double";
-const char *PoolTypeConverter<double>::AsmTag = ".quad";
-const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
-
-const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
-const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
-const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
-
-const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
-const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
-const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
-
-const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
-const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
-const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
-
-} // namespace X8664
-
-namespace X8664 {
+/// \name Limits for unrolling memory intrinsics.
+/// @{
+static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
+static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
+static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
+/// @}
 
 // The Microsoft x64 ABI requires the caller to allocate a minimum 32 byte
 // "shadow store" (aka "home space") so that the callee may copy the 4
 // register args to it.
 SizeT getShadowStoreSize() {
 #if defined(_WIN64)
-  static const SizeT ShadowStoreSize = 4 * typeWidthInBytes(Traits::WordType);
+  static const SizeT ShadowStoreSize = 4 * typeWidthInBytes(WordType);
   return ShadowStoreSize;
 #else
   return 0;
@@ -159,7 +97,7 @@
 BoolFoldingEntry::BoolFoldingEntry(Inst *I)
     : Instr(I), IsComplex(BoolFolding::hasComplexLowering(I)) {}
 
-typename BoolFolding::BoolFoldingProducerKind
+BoolFolding::BoolFoldingProducerKind
 BoolFolding::getProducerKind(const Inst *Instr) {
   if (llvm::isa<InstIcmp>(Instr)) {
     return PK_Icmp32;
@@ -188,7 +126,7 @@
   return PK_None;
 }
 
-typename BoolFolding::BoolFoldingConsumerKind
+BoolFolding::BoolFoldingConsumerKind
 BoolFolding::getConsumerKind(const Inst *Instr) {
   if (llvm::isa<InstBr>(Instr))
     return CK_Br;
@@ -222,14 +160,14 @@
   case PK_Icmp64:
     return false;
   case PK_Fcmp:
-    return Traits::TableFcmp[llvm::cast<InstFcmp>(Instr)->getCondition()].C2 !=
-           CondX86::Br_None;
+    return TargetX8664::TableFcmp[llvm::cast<InstFcmp>(Instr)->getCondition()]
+               .C2 != CondX86::Br_None;
   }
 }
 
 bool BoolFolding::isValidFolding(
-    typename BoolFolding::BoolFoldingProducerKind ProducerKind,
-    typename BoolFolding::BoolFoldingConsumerKind ConsumerKind) {
+    BoolFolding::BoolFoldingProducerKind ProducerKind,
+    BoolFolding::BoolFoldingConsumerKind ConsumerKind) {
   switch (ProducerKind) {
   default:
     return false;
@@ -268,13 +206,13 @@
         continue;
       }
       // Consumer instructions must be white-listed
-      typename BoolFolding::BoolFoldingConsumerKind ConsumerKind =
+      BoolFolding::BoolFoldingConsumerKind ConsumerKind =
           getConsumerKind(&Instr);
       if (ConsumerKind == CK_None) {
         setInvalid(VarNum);
         continue;
       }
-      typename BoolFolding::BoolFoldingProducerKind ProducerKind =
+      BoolFolding::BoolFoldingProducerKind ProducerKind =
           getProducerKind(Producers[VarNum].Instr);
       if (!isValidFolding(ProducerKind, ConsumerKind)) {
         setInvalid(VarNum);
@@ -378,13 +316,13 @@
 TargetX8664::TargetX8664(Cfg *Func) : TargetX86(Func) {}
 
 void TargetX8664::staticInit(GlobalContext *Ctx) {
-  RegNumT::setLimit(Traits::RegisterSet::Reg_NUM);
-  Traits::initRegisterSet(getFlags(), &TypeToRegisterSet, &RegisterAliases);
+  RegNumT::setLimit(RegX8664::Reg_NUM);
+  RegX8664::initRegisterSet(getFlags(), &TypeToRegisterSet, &RegisterAliases);
   for (size_t i = 0; i < TypeToRegisterSet.size(); ++i)
     TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i];
-  filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM,
-                          TypeToRegisterSet.data(), TypeToRegisterSet.size(),
-                          Traits::getRegName, getRegClassName);
+  filterTypeToRegisterSet(Ctx, RegX8664::Reg_NUM, TypeToRegisterSet.data(),
+                          TypeToRegisterSet.size(), RegX8664::getRegName,
+                          getRegClassName);
 }
 
 bool TargetX8664::shouldBePooled(const Constant *C) {
@@ -706,6 +644,12 @@
     Func->getContext()->unlockStr();
 }
 
+/// Value is in bytes. Return Value adjusted to the next highest multiple of
+/// the stack alignment.
+uint32_t TargetX8664::applyStackAlignment(uint32_t Value) {
+  return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
+}
+
 // Converts a ConstantInteger32 operand into its constant value, or
 // MemoryOrderInvalid if the operand is not a ConstantInteger32.
 inline uint64_t getConstantMemoryOrder(Operand *Opnd) {
@@ -835,7 +779,7 @@
   if (Ty == IceType_void)
     Ty = IceType_i32;
   if (PhysicalRegisters[Ty].empty())
-    PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM);
+    PhysicalRegisters[Ty].resize(RegX8664::Reg_NUM);
   assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
   Variable *Reg = PhysicalRegisters[Ty][RegNum];
   if (Reg == nullptr) {
@@ -849,12 +793,12 @@
     // Don't bother tracking the live range of a named physical register.
     Reg->setIgnoreLiveness();
   }
-  assert(Traits::getGprForType(Ty, RegNum) == RegNum);
+  assert(RegX8664::getGprForType(Ty, RegNum) == RegNum);
   return Reg;
 }
 
 const char *TargetX8664::getRegName(RegNumT RegNum, Type Ty) const {
-  return Traits::getRegName(Traits::getGprForType(Ty, RegNum));
+  return RegX8664::getRegName(RegX8664::getGprForType(Ty, RegNum));
 }
 
 void TargetX8664::emitVariable(const Variable *Var) const {
@@ -881,7 +825,7 @@
   } else if (Offset != 0) {
     Str << Offset;
   }
-  const Type FrameSPTy = Traits::WordType;
+  const Type FrameSPTy = WordType;
   Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")";
 }
 
@@ -981,19 +925,19 @@
   size_t PreservedRegsSizeBytes = 0;
   SmallBitVector Pushed(CalleeSaves.size());
   for (RegNumT i : RegNumBVIter(CalleeSaves)) {
-    const auto Canonical = Traits::getBaseReg(i);
-    assert(Canonical == Traits::getBaseReg(Canonical));
+    const auto Canonical = RegX8664::getBaseReg(i);
+    assert(Canonical == RegX8664::getBaseReg(Canonical));
     if (RegsUsed[i]) {
       Pushed[Canonical] = true;
     }
   }
   for (RegNumT RegNum : RegNumBVIter(Pushed)) {
-    assert(RegNum == Traits::getBaseReg(RegNum));
+    assert(RegNum == RegX8664::getBaseReg(RegNum));
     ++NumCallee;
-    if (Traits::isXmm(RegNum)) {
+    if (RegX8664::isXmm(RegNum)) {
       PreservedRegsSizeBytes += 16;
     } else {
-      PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType);
+      PreservedRegsSizeBytes += typeWidthInBytes(WordType);
     }
     _push_reg(RegNum);
   }
@@ -1006,7 +950,7 @@
     assert(
         (RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)).count() ==
         0);
-    PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType);
+    PreservedRegsSizeBytes += typeWidthInBytes(WordType);
     _link_bp();
   }
 
@@ -1017,7 +961,7 @@
   assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes);
   uint32_t SpillAreaPaddingBytes = 0;
   uint32_t LocalsSlotsPaddingBytes = 0;
-  alignStackSpillAreas(Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes,
+  alignStackSpillAreas(X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes,
                        SpillAreaAlignmentBytes, GlobalsSize,
                        LocalsSlotsAlignmentBytes, &SpillAreaPaddingBytes,
                        &LocalsSlotsPaddingBytes);
@@ -1025,19 +969,6 @@
   uint32_t GlobalsAndSubsequentPaddingSize =
       GlobalsSize + LocalsSlotsPaddingBytes;
 
-  // Functions returning scalar floating point types may need to convert values
-  // from an in-register xmm value to the top of the x87 floating point stack.
-  // This is done by a movp[sd] and an fld[sd].  Ensure there is enough scratch
-  // space on the stack for this.
-  const Type ReturnType = Func->getReturnType();
-  if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-    if (isScalarFloatingType(ReturnType)) {
-      // Avoid misaligned double-precision load/store.
-      SpillAreaSizeBytes =
-          std::max(typeWidthInBytesOnStack(ReturnType), SpillAreaSizeBytes);
-    }
-  }
-
   // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the
   // fixed allocations in the prolog.
   if (PrologEmitsFixedAllocas)
@@ -1052,7 +983,7 @@
   // base stack pointer (epb), whether we set it or not, to the the first stack
   // arg (if any). StackSize, on the other hand, does include the spill area.
   const uint32_t StackOffset =
-      ShadowStoreSize + Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes;
+      ShadowStoreSize + X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes;
   uint32_t StackSize = Utils::applyAlignment(StackOffset + SpillAreaSizeBytes,
                                              RequiredStackAlignment);
   StackSize = Utils::applyAlignment(StackSize + maxOutArgsSizeBytes(),
@@ -1084,7 +1015,7 @@
   // those that were register-allocated. Args are pushed right to left, so
   // Arg[0] is closest to the stack/frame pointer.
   RegNumT FrameOrStackReg = IsEbpBasedFrame ? getFrameReg() : getStackReg();
-  Variable *FramePtr = getPhysicalRegister(FrameOrStackReg, Traits::WordType);
+  Variable *FramePtr = getPhysicalRegister(FrameOrStackReg, WordType);
   size_t BasicFrameOffset = StackOffset;
   if (!IsEbpBasedFrame)
     BasicFrameOffset += SpillAreaSizeBytes;
@@ -1097,22 +1028,23 @@
     Variable *Arg = Args[i];
     // Skip arguments passed in registers.
     if (isVectorType(Arg->getType())) {
-      if (Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs))
+      if (RegX8664::getRegisterForXmmArgNum(
+              RegX8664::getArgIndex(i, NumXmmArgs))
               .hasValue()) {
         ++NumXmmArgs;
         continue;
       }
     } else if (isScalarFloatingType(Arg->getType())) {
-      if (Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-          Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs))
+      if (RegX8664::getRegisterForXmmArgNum(
+              RegX8664::getArgIndex(i, NumXmmArgs))
               .hasValue()) {
         ++NumXmmArgs;
         continue;
       }
     } else {
       assert(isScalarIntegerType(Arg->getType()));
-      if (Traits::getRegisterForGprArgNum(Traits::WordType,
-                                          Traits::getArgIndex(i, NumGPRArgs))
+      if (RegX8664::getRegisterForGprArgNum(
+              WordType, RegX8664::getArgIndex(i, NumGPRArgs))
               .hasValue()) {
         ++NumGPRArgs;
         continue;
@@ -1158,7 +1090,7 @@
         GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes -
         maxOutArgsSizeBytes();
     Str << " in-args = " << InArgsSizeBytes << " bytes\n"
-        << " return address = " << Traits::X86_RET_IP_SIZE_BYTES << " bytes\n"
+        << " return address = " << X86_RET_IP_SIZE_BYTES << " bytes\n"
         << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n"
         << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n"
         << " globals spill area = " << GlobalsSize << " bytes\n"
@@ -1193,7 +1125,7 @@
                                          size_t &InArgsSizeBytes) {
   Type Ty = Arg->getType();
   if (isVectorType(Ty)) {
-    InArgsSizeBytes = Traits::applyStackAlignment(InArgsSizeBytes);
+    InArgsSizeBytes = applyStackAlignment(InArgsSizeBytes);
   }
   Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes);
   InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
@@ -1246,7 +1178,7 @@
     const auto RegNum = RegNumT::fromInt(i);
     if (RegNum == getFrameReg() && IsEbpBasedFrame)
       continue;
-    const RegNumT Canonical = Traits::getBaseReg(RegNum);
+    const RegNumT Canonical = RegX8664::getBaseReg(RegNum);
     if (CalleeSaves[i] && RegsUsed[i]) {
       Popped[Canonical] = true;
     }
@@ -1255,16 +1187,16 @@
     if (!Popped[i])
       continue;
     const auto RegNum = RegNumT::fromInt(i);
-    assert(RegNum == Traits::getBaseReg(RegNum));
+    assert(RegNum == RegX8664::getBaseReg(RegNum));
     _pop_reg(RegNum);
   }
 }
 
-Type TargetX8664::stackSlotType() { return Traits::WordType; }
+Type TargetX8664::stackSlotType() { return WordType; }
 
 SmallBitVector TargetX8664::getRegisterSet(RegSetMask Include,
                                            RegSetMask Exclude) const {
-  return Traits::getRegisterSet(getFlags(), Include, Exclude);
+  return RegX8664::getRegisterSet(getFlags(), Include, Exclude);
 }
 
 void TargetX8664::lowerAlloca(const InstAlloca *Instr) {
@@ -1285,7 +1217,7 @@
   if (UseFramePointer)
     setHasFramePointer();
 
-  Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType);
+  Variable *esp = getPhysicalRegister(getStackReg(), WordType);
   if (OverAligned) {
     _and(esp, Ctx->getConstantInt32(-Alignment));
   }
@@ -1353,8 +1285,8 @@
     Variable *RegisterArg = nullptr;
     RegNumT RegNum;
     if (isVectorType(Ty)) {
-      RegNum =
-          Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs));
+      RegNum = RegX8664::getRegisterForXmmArgNum(
+          RegX8664::getArgIndex(i, NumXmmArgs));
       if (RegNum.hasNoValue()) {
         XmmSlotsRemain = false;
         continue;
@@ -1362,11 +1294,8 @@
       ++NumXmmArgs;
       RegisterArg = Func->makeVariable(Ty);
     } else if (isScalarFloatingType(Ty)) {
-      if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-        continue;
-      }
-      RegNum =
-          Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, NumXmmArgs));
+      RegNum = RegX8664::getRegisterForXmmArgNum(
+          RegX8664::getArgIndex(i, NumXmmArgs));
       if (RegNum.hasNoValue()) {
         XmmSlotsRemain = false;
         continue;
@@ -1374,8 +1303,8 @@
       ++NumXmmArgs;
       RegisterArg = Func->makeVariable(Ty);
     } else if (isScalarIntegerType(Ty)) {
-      RegNum = Traits::getRegisterForGprArgNum(
-          Ty, Traits::getArgIndex(i, NumGprArgs));
+      RegNum = RegX8664::getRegisterForGprArgNum(
+          Ty, RegX8664::getArgIndex(i, NumGprArgs));
       if (RegNum.hasNoValue()) {
         GprSlotsRemain = false;
         continue;
@@ -1482,7 +1411,7 @@
   constexpr uint32_t MaxOpsForOptimizedMul = 3;
   if (CountOps > MaxOpsForOptimizedMul)
     return false;
-  Variable *T = makeReg(Traits::WordType);
+  Variable *T = makeReg(WordType);
   if (typeWidthInBytes(Src0->getType()) < typeWidthInBytes(T->getType())) {
     Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
     _movzx(T, Src0RM);
@@ -1647,7 +1576,7 @@
     //   t1:ecx = c.lo & 0xff
     //   t2 = b.lo
     //   t3 = b.hi
-    T_1 = copyToReg8(Src1Lo, Traits::RegisterSet::Reg_cl);
+    T_1 = copyToReg8(Src1Lo, RegX8664::Reg_cl);
     _mov(T_2, Src0Lo);
     _mov(T_3, Src0Hi);
     switch (Op) {
@@ -1951,7 +1880,7 @@
     // The 8-bit version of imul only allows the form "imul r/m8" where T must
     // be in al.
     if (isByteSizedArithType(Ty)) {
-      _mov(T, Src0, Traits::RegisterSet::Reg_al);
+      _mov(T, Src0, RegX8664::Reg_al);
       Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
       _imul(T, Src0 == Src1 ? T : Src1);
       _mov(Dest, T);
@@ -1972,7 +1901,7 @@
     _mov(T, Src0);
     if (!llvm::isa<ConstantInteger32>(Src1) &&
         !llvm::isa<ConstantInteger64>(Src1))
-      Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
+      Src1 = copyToReg8(Src1, RegX8664::Reg_cl);
     _shl(T, Src1);
     _mov(Dest, T);
     break;
@@ -1980,7 +1909,7 @@
     _mov(T, Src0);
     if (!llvm::isa<ConstantInteger32>(Src1) &&
         !llvm::isa<ConstantInteger64>(Src1))
-      Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
+      Src1 = copyToReg8(Src1, RegX8664::Reg_cl);
     _shr(T, Src1);
     _mov(Dest, T);
     break;
@@ -1988,7 +1917,7 @@
     _mov(T, Src0);
     if (!llvm::isa<ConstantInteger32>(Src1) &&
         !llvm::isa<ConstantInteger64>(Src1))
-      Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
+      Src1 = copyToReg8(Src1, RegX8664::Reg_cl);
     _sar(T, Src1);
     _mov(Dest, T);
     break;
@@ -2002,20 +1931,20 @@
     default:
       llvm::report_fatal_error("Bad type for udiv");
     case IceType_i64:
-      Eax = Traits::getRaxOrDie();
-      Edx = Traits::getRdxOrDie();
+      Eax = RegX8664::Reg_rax;
+      Edx = RegX8664::Reg_rdx;
       break;
     case IceType_i32:
-      Eax = Traits::RegisterSet::Reg_eax;
-      Edx = Traits::RegisterSet::Reg_edx;
+      Eax = RegX8664::Reg_eax;
+      Edx = RegX8664::Reg_edx;
       break;
     case IceType_i16:
-      Eax = Traits::RegisterSet::Reg_ax;
-      Edx = Traits::RegisterSet::Reg_dx;
+      Eax = RegX8664::Reg_ax;
+      Edx = RegX8664::Reg_dx;
       break;
     case IceType_i8:
-      Eax = Traits::RegisterSet::Reg_al;
-      Edx = Traits::RegisterSet::Reg_ah;
+      Eax = RegX8664::Reg_al;
+      Edx = RegX8664::Reg_ah;
       break;
     }
     T_edx = makeReg(Ty, Edx);
@@ -2043,7 +1972,7 @@
           //   add t,src
           //   sar t,log
           //   dest=t
-          uint32_t TypeWidth = Traits::X86_CHAR_BIT * typeWidthInBytes(Ty);
+          uint32_t TypeWidth = X86_CHAR_BIT * typeWidthInBytes(Ty);
           _mov(T, Src0);
           // If for some reason we are dividing by 1, just treat it like an
           // assignment.
@@ -2065,20 +1994,20 @@
     default:
       llvm::report_fatal_error("Bad type for sdiv");
     case IceType_i64:
-      T_edx = makeReg(Ty, Traits::getRdxOrDie());
-      _mov(T, Src0, Traits::getRaxOrDie());
+      T_edx = makeReg(Ty, RegX8664::Reg_rdx);
+      _mov(T, Src0, RegX8664::Reg_rax);
       break;
     case IceType_i32:
-      T_edx = makeReg(Ty, Traits::RegisterSet::Reg_edx);
-      _mov(T, Src0, Traits::RegisterSet::Reg_eax);
+      T_edx = makeReg(Ty, RegX8664::Reg_edx);
+      _mov(T, Src0, RegX8664::Reg_eax);
       break;
     case IceType_i16:
-      T_edx = makeReg(Ty, Traits::RegisterSet::Reg_dx);
-      _mov(T, Src0, Traits::RegisterSet::Reg_ax);
+      T_edx = makeReg(Ty, RegX8664::Reg_dx);
+      _mov(T, Src0, RegX8664::Reg_ax);
       break;
     case IceType_i8:
-      T_edx = makeReg(IceType_i16, Traits::RegisterSet::Reg_ax);
-      _mov(T, Src0, Traits::RegisterSet::Reg_al);
+      T_edx = makeReg(IceType_i16, RegX8664::Reg_ax);
+      _mov(T, Src0, RegX8664::Reg_al);
       break;
     }
     _cbwdq(T_edx, T);
@@ -2094,20 +2023,20 @@
     default:
       llvm::report_fatal_error("Bad type for urem");
     case IceType_i64:
-      Eax = Traits::getRaxOrDie();
-      Edx = Traits::getRdxOrDie();
+      Eax = RegX8664::Reg_rax;
+      Edx = RegX8664::Reg_rdx;
       break;
     case IceType_i32:
-      Eax = Traits::RegisterSet::Reg_eax;
-      Edx = Traits::RegisterSet::Reg_edx;
+      Eax = RegX8664::Reg_eax;
+      Edx = RegX8664::Reg_edx;
       break;
     case IceType_i16:
-      Eax = Traits::RegisterSet::Reg_ax;
-      Edx = Traits::RegisterSet::Reg_dx;
+      Eax = RegX8664::Reg_ax;
+      Edx = RegX8664::Reg_dx;
       break;
     case IceType_i8:
-      Eax = Traits::RegisterSet::Reg_al;
-      Edx = Traits::RegisterSet::Reg_ah;
+      Eax = RegX8664::Reg_al;
+      Edx = RegX8664::Reg_ah;
       break;
     }
     T_edx = makeReg(Ty, Edx);
@@ -2145,7 +2074,7 @@
           //   sub t,src
           //   neg t
           //   dest=t
-          uint32_t TypeWidth = Traits::X86_CHAR_BIT * typeWidthInBytes(Ty);
+          uint32_t TypeWidth = X86_CHAR_BIT * typeWidthInBytes(Ty);
           // If for some reason we are dividing by 1, just assign 0.
           if (LogDiv == 0) {
             _mov(Dest, Ctx->getConstantZero(Ty));
@@ -2172,20 +2101,20 @@
     default:
       llvm::report_fatal_error("Bad type for srem");
     case IceType_i64:
-      Eax = Traits::getRaxOrDie();
-      Edx = Traits::getRdxOrDie();
+      Eax = RegX8664::Reg_rax;
+      Edx = RegX8664::Reg_rdx;
       break;
     case IceType_i32:
-      Eax = Traits::RegisterSet::Reg_eax;
-      Edx = Traits::RegisterSet::Reg_edx;
+      Eax = RegX8664::Reg_eax;
+      Edx = RegX8664::Reg_edx;
       break;
     case IceType_i16:
-      Eax = Traits::RegisterSet::Reg_ax;
-      Edx = Traits::RegisterSet::Reg_dx;
+      Eax = RegX8664::Reg_ax;
+      Edx = RegX8664::Reg_dx;
       break;
     case IceType_i8:
-      Eax = Traits::RegisterSet::Reg_al;
-      Edx = Traits::RegisterSet::Reg_ah;
+      Eax = RegX8664::Reg_al;
+      Edx = RegX8664::Reg_ah;
       break;
     }
     T_edx = makeReg(Ty, Edx);
@@ -2294,7 +2223,7 @@
   // size boundary (4 or 8 bytes, respectively).
 
   constexpr SizeT MaxOperands =
-      constexprMax(Traits::X86_MAX_XMM_ARGS, Traits::X86_MAX_GPR_ARGS);
+      constexprMax(RegX8664::X86_MAX_XMM_ARGS, RegX8664::X86_MAX_GPR_ARGS);
   using OperandList = llvm::SmallVector<Operand *, MaxOperands>;
 
   OperandList XmmArgs;
@@ -2313,20 +2242,20 @@
     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(Traits::getArgIndex(i, XmmArgs.size()))
-            .hasValue()) {
+    if (isVectorType(Ty) && RegX8664::getRegisterForXmmArgNum(
+                                RegX8664::getArgIndex(i, XmmArgs.size()))
+                                .hasValue()) {
       XmmArgs.push_back(Arg);
       XmmArgIndices.push_back(i);
-    } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-               Traits::getRegisterForXmmArgNum(
-                   Traits::getArgIndex(i, XmmArgs.size()))
+    } else if (isScalarFloatingType(Ty) &&
+               RegX8664::getRegisterForXmmArgNum(
+                   RegX8664::getArgIndex(i, XmmArgs.size()))
                    .hasValue()) {
       XmmArgs.push_back(Arg);
       XmmArgIndices.push_back(i);
     } else if (isScalarIntegerType(Ty) &&
-               Traits::getRegisterForGprArgNum(
-                   Ty, Traits::getArgIndex(i, GprArgs.size()))
+               RegX8664::getRegisterForGprArgNum(
+                   Ty, RegX8664::getArgIndex(i, GprArgs.size()))
                    .hasValue()) {
       GprArgs.emplace_back(Ty, Arg);
       GprArgIndices.push_back(i);
@@ -2334,28 +2263,17 @@
       // Place on stack.
       StackArgs.push_back(Arg);
       if (isVectorType(Arg->getType())) {
-        ParameterAreaSizeBytes =
-            Traits::applyStackAlignment(ParameterAreaSizeBytes);
+        ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
       }
-      Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType);
+      Variable *esp = getPhysicalRegister(getStackReg(), WordType);
       Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes);
       StackArgLocations.push_back(X86OperandMem::create(Func, Ty, esp, Loc));
       ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
     }
   }
-  // Ensure there is enough space for the fstp/movs for floating returns.
-  Variable *Dest = Instr->getDest();
-  const Type DestTy = Dest ? Dest->getType() : IceType_void;
-  if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-    if (isScalarFloatingType(DestTy)) {
-      ParameterAreaSizeBytes =
-          std::max(static_cast<size_t>(ParameterAreaSizeBytes),
-                   typeWidthInBytesOnStack(DestTy));
-    }
-  }
   // Adjust the parameter area so that the stack is aligned. It is assumed that
   // the stack is already aligned at the start of the calling sequence.
-  ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes);
+  ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
   assert(ParameterAreaSizeBytes <= maxOutArgsSizeBytes());
   // Copy arguments that are passed on the stack to the appropriate stack
   // locations.  We make sure legalize() is called on each argument at this
@@ -2367,8 +2285,8 @@
   // Copy arguments to be passed in registers to the appropriate registers.
   for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) {
     XmmArgs[i] = legalizeToReg(legalize(XmmArgs[i]),
-                               Traits::getRegisterForXmmArgNum(
-                                   Traits::getArgIndex(XmmArgIndices[i], i)));
+                               RegX8664::getRegisterForXmmArgNum(
+                                   RegX8664::getArgIndex(XmmArgIndices[i], i)));
   }
   // Materialize moves for arguments passed in GPRs.
   for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) {
@@ -2376,8 +2294,8 @@
     Operand *Arg =
         legalize(GprArgs[i].second, Legal_Default | Legal_Rematerializable);
     GprArgs[i].second = legalizeToReg(
-        Arg, Traits::getRegisterForGprArgNum(
-                 Arg->getType(), Traits::getArgIndex(GprArgIndices[i], i)));
+        Arg, RegX8664::getRegisterForGprArgNum(
+                 Arg->getType(), RegX8664::getArgIndex(GprArgIndices[i], i)));
     assert(SignatureTy == IceType_i64 || SignatureTy == IceType_i32);
     assert(SignatureTy == Arg->getType());
     (void)SignatureTy;
@@ -2393,9 +2311,9 @@
   }
   // Generate the call instruction. Assign its result to a temporary with high
   // register allocation weight.
-  // ReturnReg doubles as ReturnRegLo as necessary.
+  Variable *Dest = Instr->getDest();
+  const Type DestTy = Dest ? Dest->getType() : IceType_void;
   Variable *ReturnReg = nullptr;
-  Variable *ReturnRegHi = nullptr;
   if (Dest) {
     switch (DestTy) {
     case IceType_NUM:
@@ -2406,20 +2324,14 @@
       llvm::report_fatal_error("Invalid Call dest type");
       break;
     case IceType_i32:
-      ReturnReg = makeReg(DestTy, Traits::RegisterSet::Reg_eax);
+      ReturnReg = makeReg(DestTy, RegX8664::Reg_eax);
       break;
     case IceType_i64:
-      ReturnReg = makeReg(IceType_i64, Traits::getRaxOrDie());
+      ReturnReg = makeReg(IceType_i64, RegX8664::Reg_rax);
 
       break;
     case IceType_f32:
     case IceType_f64:
-      if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) {
-        // Leave ReturnReg==ReturnRegHi==nullptr, and capture the result with
-        // the fstp instruction.
-        break;
-      }
-    // Fallthrough intended.
     case IceType_v4i1:
     case IceType_v8i1:
     case IceType_v16i1:
@@ -2427,7 +2339,7 @@
     case IceType_v8i16:
     case IceType_v4i32:
     case IceType_v4f32:
-      ReturnReg = makeReg(DestTy, Traits::RegisterSet::Reg_xmm0);
+      ReturnReg = makeReg(DestTy, RegX8664::Reg_xmm0);
       break;
     }
   }
@@ -2436,9 +2348,6 @@
       legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm | Legal_AddrAbs);
   size_t NumVariadicFpArgs = Instr->isVariadic() ? XmmArgs.size() : 0;
   Inst *NewCall = emitCallToTarget(CallTarget, ReturnReg, NumVariadicFpArgs);
-  // Keep the upper return register live on 32-bit platform.
-  if (ReturnRegHi)
-    Context.insert<InstFakeDef>(ReturnRegHi);
   // Mark the call as killing all the caller-save registers.
   Context.insert<InstFakeKill>(NewCall);
   // Generate a FakeUse to keep the call live if necessary.
@@ -2498,8 +2407,7 @@
       } else {
         /// width = width(elty) - 1; dest = (src << width) >> width
         SizeT ShiftAmount =
-            Traits::X86_CHAR_BIT * typeWidthInBytes(typeElementType(DestTy)) -
-            1;
+            X86_CHAR_BIT * typeWidthInBytes(typeElementType(DestTy)) - 1;
         Constant *ShiftConstant = Ctx->getConstantInt8(ShiftAmount);
         Variable *T = makeReg(DestTy);
         _movp(T, Src0RM);
@@ -2512,7 +2420,7 @@
       // shl t1, dst_bitwidth - 1
       // sar t1, dst_bitwidth - 1
       // dst = t1
-      size_t DestBits = Traits::X86_CHAR_BIT * typeWidthInBytes(DestTy);
+      size_t DestBits = X86_CHAR_BIT * typeWidthInBytes(DestTy);
       Constant *ShiftAmount = Ctx->getConstantInt32(DestBits - 1);
       Variable *T = makeReg(DestTy);
       if (typeWidthInBytes(DestTy) <= typeWidthInBytes(Src0RM->getType())) {
@@ -2791,7 +2699,7 @@
   unsigned Index = ElementIndex->getValue();
   Type Ty = SourceVectNotLegalized->getType();
   Type ElementTy = typeElementType(Ty);
-  Type InVectorElementTy = Traits::getInVectorElementType(Ty);
+  Type InVectorElementTy = InstX86Base::getInVectorElementType(Ty);
 
   // TODO(wala): Determine the best lowering sequences for each type.
   bool CanUsePextr = Ty == IceType_v8i16 || Ty == IceType_v8i1 ||
@@ -2906,11 +2814,11 @@
   //   ucomiss b, c       /* but swap b,c order if SwapOperands==true */
   //   setcc a, C1
   InstFcmp::FCond Condition = Fcmp->getCondition();
-  assert(static_cast<size_t>(Condition) < Traits::TableFcmpSize);
-  if (Traits::TableFcmp[Condition].SwapScalarOperands)
+  assert(static_cast<size_t>(Condition) < TableFcmpSize);
+  if (TableFcmp[Condition].SwapScalarOperands)
     std::swap(Src0, Src1);
-  const bool HasC1 = (Traits::TableFcmp[Condition].C1 != CondX86::Br_None);
-  const bool HasC2 = (Traits::TableFcmp[Condition].C2 != CondX86::Br_None);
+  const bool HasC1 = (TableFcmp[Condition].C1 != CondX86::Br_None);
+  const bool HasC2 = (TableFcmp[Condition].C2 != CondX86::Br_None);
   if (HasC1) {
     Src0 = legalize(Src0);
     Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
@@ -2918,20 +2826,20 @@
     _mov(T, Src0);
     _ucomiss(T, Src1RM);
     if (!HasC2) {
-      assert(Traits::TableFcmp[Condition].Default);
-      setccOrConsumer(Traits::TableFcmp[Condition].C1, Dest, Consumer);
+      assert(TableFcmp[Condition].Default);
+      setccOrConsumer(TableFcmp[Condition].C1, Dest, Consumer);
       return;
     }
   }
-  int32_t IntDefault = Traits::TableFcmp[Condition].Default;
+  int32_t IntDefault = TableFcmp[Condition].Default;
   if (Consumer == nullptr) {
     Constant *Default = Ctx->getConstantInt(Dest->getType(), IntDefault);
     _mov(Dest, Default);
     if (HasC1) {
       InstX86Label *Label = InstX86Label::create(Func, this);
-      _br(Traits::TableFcmp[Condition].C1, Label);
+      _br(TableFcmp[Condition].C1, Label);
       if (HasC2) {
-        _br(Traits::TableFcmp[Condition].C2, Label);
+        _br(TableFcmp[Condition].C2, Label);
       }
       Constant *NonDefault = Ctx->getConstantInt(Dest->getType(), !IntDefault);
       _redefined(_mov(Dest, NonDefault));
@@ -2945,9 +2853,9 @@
     if (IntDefault != 0)
       std::swap(TrueSucc, FalseSucc);
     if (HasC1) {
-      _br(Traits::TableFcmp[Condition].C1, FalseSucc);
+      _br(TableFcmp[Condition].C1, FalseSucc);
       if (HasC2) {
-        _br(Traits::TableFcmp[Condition].C2, FalseSucc);
+        _br(TableFcmp[Condition].C2, FalseSucc);
       }
       _br(TrueSucc);
       return;
@@ -2964,9 +2872,9 @@
     lowerMove(SelectDest, SrcF, false);
     if (HasC1) {
       InstX86Label *Label = InstX86Label::create(Func, this);
-      _br(Traits::TableFcmp[Condition].C1, Label);
+      _br(TableFcmp[Condition].C1, Label);
       if (HasC2) {
-        _br(Traits::TableFcmp[Condition].C2, Label);
+        _br(TableFcmp[Condition].C2, Label);
       }
       static constexpr bool IsRedefinition = true;
       lowerMove(SelectDest, SrcT, IsRedefinition);
@@ -2986,9 +2894,9 @@
     llvm::report_fatal_error("Expected vector compare");
 
   InstFcmp::FCond Condition = Fcmp->getCondition();
-  assert(static_cast<size_t>(Condition) < Traits::TableFcmpSize);
+  assert(static_cast<size_t>(Condition) < TableFcmpSize);
 
-  if (Traits::TableFcmp[Condition].SwapVectorOperands)
+  if (TableFcmp[Condition].SwapVectorOperands)
     std::swap(Src0, Src1);
 
   Variable *T = nullptr;
@@ -3006,7 +2914,7 @@
 
     switch (Condition) {
     default: {
-      const CmppsCond Predicate = Traits::TableFcmp[Condition].Predicate;
+      const CmppsCond Predicate = TableFcmp[Condition].Predicate;
       assert(Predicate != CondX86::Cmpps_Invalid);
       T = makeReg(Src0RM->getType());
       _movp(T, Src0RM);
@@ -3076,8 +2984,7 @@
   }
   Operand *Src0RM = legalizeSrc0ForCmp(Src0, Src1);
   _cmp(Src0RM, Src1);
-  setccOrConsumer(Traits::getIcmp32Mapping(Icmp->getCondition()), Dest,
-                  Consumer);
+  setccOrConsumer(getIcmp32Mapping(Icmp->getCondition()), Dest, Consumer);
 }
 
 void TargetX8664::lowerIcmpVector(const InstIcmp *Icmp) {
@@ -3293,7 +3200,7 @@
 
   Type Ty = SourceVectNotLegalized->getType();
   Type ElementTy = typeElementType(Ty);
-  Type InVectorElementTy = Traits::getInVectorElementType(Ty);
+  Type InVectorElementTy = InstX86Base::getInVectorElementType(Ty);
 
   if (ElementTy == IceType_i1) {
     // Expand the element to the appropriate size for it to be inserted in the
@@ -3673,7 +3580,7 @@
   }
   case Intrinsics::Stacksave: {
     Variable *rsp =
-        Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
+        Func->getTarget()->getPhysicalRegister(getStackReg(), WordType);
     Variable *Dest = Instr->getDest();
     _mov(Dest, rsp);
     return;
@@ -3931,16 +3838,16 @@
   default:
     llvm::report_fatal_error("Bad type for cmpxchg");
   case IceType_i64:
-    Eax = Traits::getRaxOrDie();
+    Eax = RegX8664::Reg_rax;
     break;
   case IceType_i32:
-    Eax = Traits::RegisterSet::Reg_eax;
+    Eax = RegX8664::Reg_eax;
     break;
   case IceType_i16:
-    Eax = Traits::RegisterSet::Reg_ax;
+    Eax = RegX8664::Reg_ax;
     break;
   case IceType_i8:
-    Eax = Traits::RegisterSet::Reg_al;
+    Eax = RegX8664::Reg_al;
     break;
   }
   Variable *T_eax = makeReg(Ty, Eax);
@@ -4122,16 +4029,16 @@
   default:
     llvm::report_fatal_error("Bad type for atomicRMW");
   case IceType_i64:
-    Eax = Traits::getRaxOrDie();
+    Eax = RegX8664::Reg_rax;
     break;
   case IceType_i32:
-    Eax = Traits::RegisterSet::Reg_eax;
+    Eax = RegX8664::Reg_eax;
     break;
   case IceType_i16:
-    Eax = Traits::RegisterSet::Reg_ax;
+    Eax = RegX8664::Reg_ax;
     break;
   case IceType_i8:
-    Eax = Traits::RegisterSet::Reg_al;
+    Eax = RegX8664::Reg_al;
     break;
   }
   Variable *T_eax = makeReg(Ty, Eax);
@@ -4283,7 +4190,7 @@
   const uint32_t CountValue = IsCountConst ? CountConst->getValue() : 0;
 
   if (shouldOptimizeMemIntrins() && IsCountConst &&
-      CountValue <= BytesPerStorep * Traits::MEMCPY_UNROLL_LIMIT) {
+      CountValue <= BytesPerStorep * MEMCPY_UNROLL_LIMIT) {
     // Unlikely, but nothing to do if it does happen
     if (CountValue == 0)
       return;
@@ -4335,7 +4242,7 @@
   const uint32_t CountValue = IsCountConst ? CountConst->getValue() : 0;
 
   if (shouldOptimizeMemIntrins() && IsCountConst &&
-      CountValue <= BytesPerStorep * Traits::MEMMOVE_UNROLL_LIMIT) {
+      CountValue <= BytesPerStorep * MEMMOVE_UNROLL_LIMIT) {
     // Unlikely, but nothing to do if it does happen
     if (CountValue == 0)
       return;
@@ -4343,8 +4250,7 @@
     Variable *SrcBase = legalizeToReg(Src);
     Variable *DestBase = legalizeToReg(Dest);
 
-    std::tuple<Type, Constant *, Variable *>
-        Moves[Traits::MEMMOVE_UNROLL_LIMIT];
+    std::tuple<Type, Constant *, Variable *> Moves[MEMMOVE_UNROLL_LIMIT];
     Constant *Offset;
     Variable *Reg;
 
@@ -4358,7 +4264,7 @@
     int32_t OffsetAmt = (CountValue & ~(TyWidth - 1)) - TyWidth;
     size_t N = 0;
     while (RemainingBytes >= TyWidth) {
-      assert(N <= Traits::MEMMOVE_UNROLL_LIMIT);
+      assert(N <= MEMMOVE_UNROLL_LIMIT);
       Offset = Ctx->getConstantInt32(OffsetAmt);
       Reg = makeReg(Ty);
       typedLoad(Ty, Reg, SrcBase, Offset);
@@ -4370,7 +4276,7 @@
     if (RemainingBytes != 0) {
       // Lower the remaining bytes. Adjust to larger types in order to make use
       // of overlaps in the copies.
-      assert(N <= Traits::MEMMOVE_UNROLL_LIMIT);
+      assert(N <= MEMMOVE_UNROLL_LIMIT);
       Ty = firstTypeThatFitsSize(RemainingBytes);
       Offset = Ctx->getConstantInt32(CountValue - typeWidthInBytes(Ty));
       Reg = makeReg(Ty);
@@ -4448,13 +4354,13 @@
     // memory unit as the access to the same memory are far apart.
     Type Ty = IceType_void;
     if (ValValue == 0 && CountValue >= BytesPerStoreq &&
-        CountValue <= BytesPerStorep * Traits::MEMSET_UNROLL_LIMIT) {
+        CountValue <= BytesPerStorep * MEMSET_UNROLL_LIMIT) {
       // When the value is zero it can be loaded into a vector register cheaply
       // using the xor trick.
       Base = legalizeToReg(Dest);
       VecReg = makeVectorOfZeros(IceType_v16i8);
       Ty = largestTypeInSize(CountValue);
-    } else if (CountValue <= BytesPerStorei32 * Traits::MEMSET_UNROLL_LIMIT) {
+    } else if (CountValue <= BytesPerStorei32 * MEMSET_UNROLL_LIMIT) {
       // When the value is non-zero or the count is small we can't use vector
       // instructions so are limited to 32-bit stores.
       Base = legalizeToReg(Dest);
@@ -5874,7 +5780,7 @@
     if (SrcTy == IceType_v4i1 || SrcTy == IceType_v4i32 ||
         SrcTy == IceType_v4f32) {
       Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem);
-      Variable *xmm0 = makeReg(IceType_v4i32, Traits::RegisterSet::Reg_xmm0);
+      Variable *xmm0 = makeReg(IceType_v4i32, RegX8664::Reg_xmm0);
       _movp(xmm0, ConditionRM);
       _psll(xmm0, Ctx->getConstantInt8(31));
       _movp(T, SrcFRM);
@@ -5884,7 +5790,7 @@
       assert(typeNumElements(SrcTy) == 8 || typeNumElements(SrcTy) == 16);
       Type SignExtTy =
           Condition->getType() == IceType_v8i1 ? IceType_v8i16 : IceType_v16i8;
-      Variable *xmm0 = makeReg(SignExtTy, Traits::RegisterSet::Reg_xmm0);
+      Variable *xmm0 = makeReg(SignExtTy, RegX8664::Reg_xmm0);
       lowerCast(InstCast::create(Func, InstCast::Sext, xmm0, Condition));
       _movp(T, SrcFRM);
       _pblendvb(T, SrcTRM, xmm0);
@@ -5892,7 +5798,7 @@
     }
     return;
   }
-  // Lower select without Traits::SSE4.1:
+  // Lower select without SSE4.1:
   // a=d?b:c ==>
   //   if elementtype(d) != i1:
   //      d=sext(d);
@@ -6435,7 +6341,7 @@
   } else {
     return;
   }
-  StackArgumentsSize = Traits::applyStackAlignment(StackArgumentsSize);
+  StackArgumentsSize = applyStackAlignment(StackArgumentsSize);
   updateMaxOutArgsSizeBytes(StackArgumentsSize);
 }
 
@@ -6450,24 +6356,23 @@
     // The PNaCl ABI requires the width of arguments to be at least 32 bits.
     assert(typeWidthInBytes(Ty) >= 4);
     if (isVectorType(Ty) &&
-        Traits::getRegisterForXmmArgNum(Traits::getArgIndex(i, XmmArgCount))
+        RegX8664::getRegisterForXmmArgNum(RegX8664::getArgIndex(i, XmmArgCount))
             .hasValue()) {
       ++XmmArgCount;
-    } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM &&
-               Traits::getRegisterForXmmArgNum(
-                   Traits::getArgIndex(i, XmmArgCount))
+    } else if (isScalarFloatingType(Ty) &&
+               RegX8664::getRegisterForXmmArgNum(
+                   RegX8664::getArgIndex(i, XmmArgCount))
                    .hasValue()) {
       ++XmmArgCount;
     } else if (isScalarIntegerType(Ty) &&
-               Traits::getRegisterForGprArgNum(
-                   Ty, Traits::getArgIndex(i, GprArgCount))
+               RegX8664::getRegisterForGprArgNum(
+                   Ty, RegX8664::getArgIndex(i, GprArgCount))
                    .hasValue()) {
       // The 64 bit ABI allows some integers to be passed in GPRs.
       ++GprArgCount;
     } else {
       if (isVectorType(Ty)) {
-        OutArgumentsSizeBytes =
-            Traits::applyStackAlignment(OutArgumentsSizeBytes);
+        OutArgumentsSizeBytes = applyStackAlignment(OutArgumentsSizeBytes);
       }
       OutArgumentsSizeBytes += typeWidthInBytesOnStack(Ty);
     }
@@ -6557,8 +6462,7 @@
          Ty == IceType_v16i8);
   if (Ty == IceType_v4f32 || Ty == IceType_v4i32 || Ty == IceType_v8i16) {
     Variable *Reg = makeVectorOfOnes(Ty, RegNum);
-    SizeT Shift =
-        typeWidthInBytes(typeElementType(Ty)) * Traits::X86_CHAR_BIT - 1;
+    SizeT Shift = typeWidthInBytes(typeElementType(Ty)) * X86_CHAR_BIT - 1;
     _psll(Reg, Ctx->getConstantInt8(Shift));
     return Reg;
   } else {
@@ -6756,7 +6660,7 @@
     if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Const)) {
       if (!Utils::IsInt(32, C64->getValue())) {
         if (RegNum.hasValue()) {
-          assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
+          assert(RegX8664::getGprForType(IceType_i64, RegNum) == RegNum);
         }
         return copyToReg(Const, RegNum);
       }
@@ -6997,6 +6901,31 @@
   Str << "\n";
 }
 
+const TargetX8664::TableFcmpType TargetX8664::TableFcmp[] = {
+#define X(val, dflt, swapS, C1, C2, swapV, pred)                               \
+  {dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred},
+    FCMPX8664_TABLE
+#undef X
+};
+
+const size_t TargetX8664::TableFcmpSize = llvm::array_lengthof(TableFcmp);
+
+const TargetX8664::TableIcmp32Type TargetX8664::TableIcmp32[] = {
+#define X(val, C_32, C1_64, C2_64, C3_64) {CondX86::C_32},
+    ICMPX8664_TABLE
+#undef X
+};
+
+const size_t TargetX8664::TableIcmp32Size = llvm::array_lengthof(TableIcmp32);
+
+std::array<SmallBitVector, RCX86_NUM> TargetX8664::TypeToRegisterSet = {{}};
+
+std::array<SmallBitVector, RCX86_NUM> TargetX8664::TypeToRegisterSetUnfiltered =
+    {{}};
+
+std::array<SmallBitVector, RegX8664::Reg_NUM> TargetX8664::RegisterAliases = {
+    {}};
+
 template <typename T>
 void TargetDataX8664::emitConstantPool(GlobalContext *Ctx) {
   if (!BuildDefs::dump())
@@ -7115,64 +7044,6 @@
 }
 
 //------------------------------------------------------------------------------
-//      ______   ______     ______     __     ______   ______
-//     /\__  _\ /\  == \   /\  __ \   /\ \   /\__  _\ /\  ___\
-//     \/_/\ \/ \ \  __<   \ \  __ \  \ \ \  \/_/\ \/ \ \___  \
-//        \ \_\  \ \_\ \_\  \ \_\ \_\  \ \_\    \ \_\  \/\_____\
-//         \/_/   \/_/ /_/   \/_/\/_/   \/_/     \/_/   \/_____/
-//
-//------------------------------------------------------------------------------
-const TargetX8664Traits::TableFcmpType TargetX8664Traits::TableFcmp[] = {
-#define X(val, dflt, swapS, C1, C2, swapV, pred)                               \
-  {dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred},
-    FCMPX8664_TABLE
-#undef X
-};
-
-const size_t TargetX8664Traits::TableFcmpSize = llvm::array_lengthof(TableFcmp);
-
-const TargetX8664Traits::TableIcmp32Type TargetX8664Traits::TableIcmp32[] = {
-#define X(val, C_32, C1_64, C2_64, C3_64) {CondX86::C_32},
-    ICMPX8664_TABLE
-#undef X
-};
-
-const size_t TargetX8664Traits::TableIcmp32Size =
-    llvm::array_lengthof(TableIcmp32);
-
-const TargetX8664Traits::TableIcmp64Type TargetX8664Traits::TableIcmp64[] = {
-#define X(val, C_32, C1_64, C2_64, C3_64)                                      \
-  {CondX86::C1_64, CondX86::C2_64, CondX86::C3_64},
-    ICMPX8664_TABLE
-#undef X
-};
-
-const size_t TargetX8664Traits::TableIcmp64Size =
-    llvm::array_lengthof(TableIcmp64);
-
-const TargetX8664Traits::TableTypeX8664AttributesType
-    TargetX8664Traits::TableTypeX8664Attributes[] = {
-#define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld)    \
-  {IceType_##elty},
-        ICETYPEX86_TABLE
-#undef X
-};
-
-const size_t TargetX8664Traits::TableTypeX8664AttributesSize =
-    llvm::array_lengthof(TableTypeX8664Attributes);
-
-const uint32_t TargetX8664Traits::X86_STACK_ALIGNMENT_BYTES = 16;
-const char *TargetX8664Traits::TargetName = "X8664";
-
-std::array<SmallBitVector, RCX86_NUM> TargetX8664::TypeToRegisterSet = {{}};
-
-std::array<SmallBitVector, RCX86_NUM> TargetX8664::TypeToRegisterSetUnfiltered =
-    {{}};
-
-std::array<SmallBitVector, RegisterSet::Reg_NUM> TargetX8664::RegisterAliases =
-    {{}};
-
-//------------------------------------------------------------------------------
 //     __      ______  __     __  ______  ______  __  __   __  ______
 //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
 //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
@@ -7181,22 +7052,18 @@
 //
 //------------------------------------------------------------------------------
 void TargetX8664::_add_sp(Operand *Adjustment) {
-  Variable *rsp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
+  Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, IceType_i64);
   _add(rsp, Adjustment);
 }
 
 void TargetX8664::_mov_sp(Operand *NewValue) {
-  Variable *rsp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
+  Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, IceType_i64);
   _redefined(_mov(rsp, NewValue));
 }
 
 void TargetX8664::_link_bp() {
-  Variable *rsp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rsp, Traits::WordType);
-  Variable *rbp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rbp, Traits::WordType);
+  Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, WordType);
+  Variable *rbp = getPhysicalRegister(RegX8664::Reg_rbp, WordType);
 
   _push(rbp);
   _mov(rbp, rsp);
@@ -7205,10 +7072,8 @@
 }
 
 void TargetX8664::_unlink_bp() {
-  Variable *rsp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64);
-  Variable *rbp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64);
+  Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, IceType_i64);
+  Variable *rbp = getPhysicalRegister(RegX8664::Reg_rbp, IceType_i64);
   // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake
   // use of rsp before the assignment of rsp=rbp keeps previous rsp
   // adjustments from being dead-code eliminated.
@@ -7219,38 +7084,35 @@
 }
 
 void TargetX8664::_push_reg(RegNumT RegNum) {
-  if (Traits::isXmm(RegNum)) {
+  if (RegX8664::isXmm(RegNum)) {
     Variable *reg = getPhysicalRegister(RegNum, IceType_v4f32);
-    Variable *rsp =
-        getPhysicalRegister(Traits::RegisterSet::Reg_rsp, Traits::WordType);
+    Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, WordType);
     auto *address = X86OperandMem::create(Func, reg->getType(), rsp, nullptr);
     _sub_sp(
         Ctx->getConstantInt32(16)); // TODO(capn): accumulate all the offsets
                                     // and adjust the stack pointer once.
     _storep(reg, address);
   } else {
-    _push(getPhysicalRegister(RegNum, Traits::WordType));
+    _push(getPhysicalRegister(RegNum, WordType));
   }
 }
 
 void TargetX8664::_pop_reg(RegNumT RegNum) {
-  if (Traits::isXmm(RegNum)) {
+  if (RegX8664::isXmm(RegNum)) {
     Variable *reg = getPhysicalRegister(RegNum, IceType_v4f32);
-    Variable *rsp =
-        getPhysicalRegister(Traits::RegisterSet::Reg_rsp, Traits::WordType);
+    Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, WordType);
     auto *address = X86OperandMem::create(Func, reg->getType(), rsp, nullptr);
     _movp(reg, address);
     _add_sp(
         Ctx->getConstantInt32(16)); // TODO(capn): accumulate all the offsets
                                     // and adjust the stack pointer once.
   } else {
-    _pop(getPhysicalRegister(RegNum, Traits::WordType));
+    _pop(getPhysicalRegister(RegNum, WordType));
   }
 }
 
 void TargetX8664::_sub_sp(Operand *Adjustment) {
-  Variable *rsp =
-      getPhysicalRegister(Traits::RegisterSet::Reg_rsp, Traits::WordType);
+  Variable *rsp = getPhysicalRegister(RegX8664::Reg_rsp, WordType);
 
   _sub(rsp, Adjustment);
 
@@ -7281,7 +7143,7 @@
     // usage below).
 #if !defined(SUBZERO_USE_MICROSOFT_ABI)
     if (NumVariadicFpArgs > 0)
-      TargetReg = Traits::RegisterSet::Reg_r11;
+      TargetReg = RegX8664::Reg_r11;
 #endif
 
     if (llvm::isa<Constant>(CallTarget)) {
@@ -7300,8 +7162,7 @@
     // Store number of FP args (stored in XMM registers) in RAX for variadic
     // calls
     auto *NumFpArgs = Ctx->getConstantInt64(NumVariadicFpArgs);
-    Variable *NumFpArgsReg =
-        legalizeToReg(NumFpArgs, Traits::RegisterSet::Reg_rax);
+    Variable *NumFpArgsReg = legalizeToReg(NumFpArgs, RegX8664::Reg_rax);
     Context.insert<InstFakeUse>(NumFpArgsReg);
   }
 #endif
@@ -7312,12 +7173,11 @@
 Variable *TargetX8664::moveReturnValueToRegister(Operand *Value,
                                                  Type ReturnType) {
   if (isVectorType(ReturnType) || isScalarFloatingType(ReturnType)) {
-    return legalizeToReg(Value, Traits::RegisterSet::Reg_xmm0);
+    return legalizeToReg(Value, RegX8664::Reg_xmm0);
   } else {
     assert(ReturnType == IceType_i32 || ReturnType == IceType_i64);
     Variable *Reg = nullptr;
-    _mov(Reg, Value,
-         Traits::getGprForType(ReturnType, Traits::RegisterSet::Reg_rax));
+    _mov(Reg, Value, RegX8664::getGprForType(ReturnType, RegX8664::Reg_rax));
     return Reg;
   }
 }
@@ -7330,13 +7190,12 @@
     // __chkstk on Win64 probes the stack up to RSP - EAX, but does not clobber
     // RSP, so we don't need to save and restore it.
 
-    Variable *EAX = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
+    Variable *EAX = makeReg(IceType_i32, RegX8664::Reg_eax);
     _mov(EAX, Ctx->getConstantInt32(StackSizeBytes));
 
     auto *CallTarget =
         Ctx->getConstantInt64(reinterpret_cast<int64_t>(&__chkstk));
-    Operand *CallTargetReg =
-        legalizeToReg(CallTarget, Traits::RegisterSet::Reg_r11);
+    Operand *CallTargetReg = legalizeToReg(CallTarget, RegX8664::Reg_r11);
     emitCallToTarget(CallTargetReg, nullptr);
   }
 #endif
diff --git a/third_party/subzero/src/IceTargetLoweringX8664.h b/third_party/subzero/src/IceTargetLoweringX8664.h
index e6cce45..401b55e 100644
--- a/third_party/subzero/src/IceTargetLoweringX8664.h
+++ b/third_party/subzero/src/IceTargetLoweringX8664.h
@@ -24,7 +24,6 @@
 #include "IceInstX8664.h"
 #include "IceSwitchLowering.h"
 #include "IceTargetLoweringX86.h"
-#include "IceTargetLoweringX8664Traits.h"
 #include "IceTargetLoweringX86RegClass.h"
 #include "IceUtils.h"
 
@@ -37,6 +36,8 @@
 
 using namespace ::Ice::X86;
 
+constexpr Type WordType = IceType_i64;
+
 class BoolFoldingEntry {
   BoolFoldingEntry(const BoolFoldingEntry &) = delete;
 
@@ -104,22 +105,13 @@
   CfgUnorderedMap<SizeT, BoolFoldingEntry> Producers;
 };
 
-/// TargetX8664 is a template for all X86 Targets, and it relies on the CRT
-/// pattern for generating code, delegating to actual backends target-specific
-/// lowerings (e.g., call, ret, and intrinsics.)
-///
-/// Note: Ideally, we should be able to
-///
-///  static_assert(std::is_base_of<TargetX8664<TraitsType>,
-///  Machine>::value);
-///
-/// but that does not work: the compiler does not know that Machine inherits
-/// from TargetX8664 at this point in translation.
 class TargetX8664 : public TargetX86 {
   TargetX8664() = delete;
   TargetX8664(const TargetX8664 &) = delete;
   TargetX8664 &operator=(const TargetX8664 &) = delete;
 
+  friend class BoolFolding;
+
 public:
   using BrCond = CondX86::BrCond;
   using CmppsCond = CondX86::CmppsCond;
@@ -141,9 +133,7 @@
   void doLoadOpt();
   bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
 
-  SizeT getNumRegisters() const override {
-    return Traits::RegisterSet::Reg_NUM;
-  }
+  SizeT getNumRegisters() const override { return RegisterSet::Reg_NUM; }
 
   Inst *createLoweredMove(Variable *Dest, Variable *SrcVar) override {
     if (isVectorType(Dest->getType())) {
@@ -211,16 +201,16 @@
   }
   size_t typeWidthInBytesOnStack(Type Ty) const override {
     // Round up to the next multiple of WordType bytes.
-    const uint32_t WordSizeInBytes = typeWidthInBytes(Traits::WordType);
+    const uint32_t WordSizeInBytes = typeWidthInBytes(WordType);
     return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes);
   }
   uint32_t getStackAlignment() const override {
-    return Traits::X86_STACK_ALIGNMENT_BYTES;
+    return X86_STACK_ALIGNMENT_BYTES;
   }
   bool needsStackPointerAlignment() const override {
-    // If the ABI's stack alignment is smaller than the vector size (16 bytes),
+    // If the ABI's stack alignment is smaller than the vector size,
     // use the (realigned) stack pointer for addressing any stack variables.
-    return Traits::X86_STACK_ALIGNMENT_BYTES < 16;
+    return X86_STACK_ALIGNMENT_BYTES < RequiredStackAlignment;
   }
   void reserveFixedAllocaArea(size_t Size, size_t Align) override {
     FixedAllocaSizeBytes = Size;
@@ -377,7 +367,7 @@
   /// function. Otherwise some esp adjustments get dead-code eliminated.
   void keepEspLiveAtExit() {
     Variable *esp =
-        Func->getTarget()->getPhysicalRegister(getStackReg(), Traits::WordType);
+        Func->getTarget()->getPhysicalRegister(getStackReg(), WordType);
     Context.insert<InstFakeUse>(esp);
   }
 
@@ -492,7 +482,7 @@
     Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far);
   }
   void _br(BrCond Condition, InstX86Label *Label,
-           typename InstX86Br::Mode Kind = InstX86Br::Near) {
+           InstX86Br::Mode Kind = InstX86Br::Near) {
     Context.insert<InstX86Br>(Label, Condition, Kind);
   }
   void _bsf(Variable *Dest, Operand *Src0) {
@@ -857,8 +847,14 @@
   bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
   void findRMW();
 
+  static uint32_t applyStackAlignment(uint32_t Value);
+
   bool IsEbpBasedFrame = false;
-  static constexpr uint32_t RequiredStackAlignment = 16;
+
+  /// Stack alignment guaranteed by the ABI.
+  static constexpr uint32_t X86_STACK_ALIGNMENT_BYTES = 16;
+  /// Stack alignment required by the currently lowered function.
+  const uint32_t RequiredStackAlignment = X86_STACK_ALIGNMENT_BYTES;
   size_t SpillAreaSizeBytes = 0;
   size_t FixedAllocaSizeBytes = 0;
   size_t FixedAllocaAlignBytes = 0;
@@ -866,8 +862,7 @@
   uint32_t MaxOutArgsSizeBytes = 0;
   static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet;
   static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered;
-  static std::array<SmallBitVector, Traits::RegisterSet::Reg_NUM>
-      RegisterAliases;
+  static std::array<SmallBitVector, RegisterSet::Reg_NUM> RegisterAliases;
   SmallBitVector RegsUsed;
   std::array<VarList, IceType_NUM> PhysicalRegisters;
 
@@ -939,6 +934,60 @@
                                       int8_t Idx14, int8_t Idx15);
   /// @}
 
+  /// The following table summarizes the logic for lowering the fcmp
+  /// instruction. There is one table entry for each of the 16 conditions.
+  ///
+  /// The first four columns describe the case when the operands are floating
+  /// point scalar values. A comment in lowerFcmp() describes the lowering
+  /// template. In the most general case, there is a compare followed by two
+  /// conditional branches, because some fcmp conditions don't map to a single
+  /// x86 conditional branch. However, in many cases it is possible to swap the
+  /// operands in the comparison and have a single conditional branch. Since
+  /// it's quite tedious to validate the table by hand, good execution tests are
+  /// helpful.
+  ///
+  /// The last two columns describe the case when the operands are vectors of
+  /// floating point values. For most fcmp conditions, there is a clear mapping
+  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
+  /// special code to handle and these are marked in the table with a
+  /// Cmpps_Invalid predicate.
+  /// {@
+  static const struct TableFcmpType {
+    uint32_t Default;
+    bool SwapScalarOperands;
+    CondX86::BrCond C1, C2;
+    bool SwapVectorOperands;
+    CondX86::CmppsCond Predicate;
+  } TableFcmp[];
+  static const size_t TableFcmpSize;
+  /// @}
+
+  /// The following table summarizes the logic for lowering the icmp instruction
+  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
+  /// x86 conditional branch instruction.
+  /// {@
+  static const struct TableIcmp32Type {
+    CondX86::BrCond Mapping;
+  } TableIcmp32[];
+  static const size_t TableIcmp32Size;
+  /// @}
+
+  /// The following table summarizes the logic for lowering the icmp instruction
+  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
+  /// conditional branches are needed. For the other conditions, three separate
+  /// conditional branches are needed.
+  /// {@
+  static const struct TableIcmp64Type {
+    CondX86::BrCond C1, C2, C3;
+  } TableIcmp64[];
+  static const size_t TableIcmp64Size;
+  /// @}
+
+  static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
+    assert(Cond < TableIcmp32Size);
+    return TableIcmp32[Cond].Mapping;
+  }
+
 public:
   static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
     return makeUnique<TargetX8664>(Func);
@@ -955,7 +1004,6 @@
 };
 
 class TargetDataX8664 final : public TargetDataLowering {
-  using Traits = TargetX8664Traits;
   TargetDataX8664() = delete;
   TargetDataX8664(const TargetDataX8664 &) = delete;
   TargetDataX8664 &operator=(const TargetDataX8664 &) = delete;
diff --git a/third_party/subzero/src/IceTargetLoweringX8664Traits.h b/third_party/subzero/src/IceTargetLoweringX8664Traits.h
deleted file mode 100644
index edeac04..0000000
--- a/third_party/subzero/src/IceTargetLoweringX8664Traits.h
+++ /dev/null
@@ -1,580 +0,0 @@
-//===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=//
-//
-//                        The Subzero Code Generator
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Declares the X8664 Target Lowering Traits.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
-#define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
-
-#include "IceAssembler.h"
-#include "IceConditionCodesX86.h"
-#include "IceDefs.h"
-#include "IceInst.h"
-#include "IceOperand.h"
-#include "IceRegistersX8664.h"
-#include "IceTargetLowering.h"
-#include "IceTargetLoweringX8664.def"
-#include "IceTargetLoweringX86RegClass.h"
-
-#include <array>
-#include <initializer_list>
-
-namespace Ice {
-namespace X8664 {
-using namespace ::Ice::X86;
-
-class AssemblerX8664;
-struct Insts;
-class TargetX8664;
-class TargetX8664;
-
-struct TargetX8664Traits {
-  using RegisterSet = ::Ice::RegX8664;
-  using GPRRegister = RegisterSet::GPRRegister;
-  using ByteRegister = RegisterSet::ByteRegister;
-  using XmmRegister = RegisterSet::XmmRegister;
-
-  //----------------------------------------------------------------------------
-  //     __      ______  __     __  ______  ______  __  __   __  ______
-  //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
-  //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
-  //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
-  //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
-  //
-  //----------------------------------------------------------------------------
-  static const char *TargetName;
-  static constexpr Type WordType = IceType_i64;
-
-  static const char *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,      \
-          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  name,
-        REGX8664_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    return RegNames[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,      \
-          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
-        REGX8664_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
-    return GPRRegs[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,      \
-          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
-        REGX8664_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
-    return ByteRegs[RegNum];
-  }
-
-  static bool isXmm(RegNumT RegNum) {
-    static const bool IsXmm[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)                            \
-  isXmm,
-        REGX8664_TABLE
-#undef X
-    };
-    return IsXmm[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,      \
-          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
-        REGX8664_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
-    return XmmRegs[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,      \
-          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  encode,
-        REGX8664_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    return Encoding[RegNum];
-  }
-
-  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)                            \
-  RegisterSet::base,
-        REGX8664_TABLE
-#undef X
-    };
-    RegNum.assertIsValid();
-    return BaseRegs[RegNum];
-  }
-
-private:
-  static RegNumT getFirstGprForType(Type Ty) {
-    switch (Ty) {
-    default:
-      llvm_unreachable("Invalid type for GPR.");
-    case IceType_i1:
-    case IceType_i8:
-      return RegisterSet::Reg_al;
-    case IceType_i16:
-      return RegisterSet::Reg_ax;
-    case IceType_i32:
-      return RegisterSet::Reg_eax;
-    case IceType_i64:
-      return RegisterSet::Reg_rax;
-    }
-  }
-
-public:
-  static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
-    assert(RegNum.hasValue());
-
-    if (!isScalarIntegerType(Ty)) {
-      return RegNum;
-    }
-
-    assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 ||
-           Ty == IceType_i32 || Ty == IceType_i64);
-
-    if (RegNum == RegisterSet::Reg_ah) {
-      assert(Ty == IceType_i8);
-      return RegNum;
-    }
-
-    assert(RegNum != RegisterSet::Reg_bh);
-    assert(RegNum != RegisterSet::Reg_ch);
-    assert(RegNum != RegisterSet::Reg_dh);
-
-    const RegNumT FirstGprForType = getFirstGprForType(Ty);
-
-    switch (RegNum) {
-    default:
-      llvm::report_fatal_error("Unknown register.");
-#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
-          sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8,      \
-          is16To8, isTrunc8Rcvr, isAhRcvr, aliases)                            \
-  case RegisterSet::val: {                                                     \
-    if (!isGPR)                                                                \
-      return RegisterSet::val;                                                 \
-    assert((is64) || (is32) || (is16) || (is8) ||                              \
-           getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp);              \
-    constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize =               \
-        ((is64) || RegisterSet::val == RegisterSet::Reg_rsp)                   \
-            ? RegisterSet::Reg_rax                                             \
-            : (((is32) || RegisterSet::val == RegisterSet::Reg_esp)            \
-                   ? RegisterSet::Reg_eax                                      \
-                   : (((is16) || RegisterSet::val == RegisterSet::Reg_sp)      \
-                          ? RegisterSet::Reg_ax                                \
-                          : RegisterSet::Reg_al));                             \
-    const auto NewRegNum =                                                     \
-        RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
-    assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
-           "Error involving " #val);                                           \
-    return NewRegNum;                                                          \
-  }
-      REGX8664_TABLE
-#undef X
-    }
-  }
-
-private:
-  /// SizeOf is used to obtain the size of an initializer list as a constexpr
-  /// expression. This is only needed until our C++ library is updated to
-  /// C++ 14 -- which defines constexpr members to std::initializer_list.
-  class SizeOf {
-    SizeOf(const SizeOf &) = delete;
-    SizeOf &operator=(const SizeOf &) = delete;
-
-  public:
-    constexpr SizeOf() : Size(0) {}
-    template <typename... T>
-    explicit constexpr SizeOf(T...) : Size(length<T...>::value) {}
-    constexpr SizeT size() const { return Size; }
-
-  private:
-    template <typename T, typename... U> struct length {
-      static constexpr std::size_t value = 1 + length<U...>::value;
-    };
-
-    template <typename T> struct length<T> {
-      static constexpr std::size_t value = 1;
-    };
-
-    const std::size_t Size;
-  };
-
-public:
-  static void initRegisterSet(
-      const ::Ice::ClFlags &Flags,
-      std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
-      std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
-    SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM);
-    SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
-    SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
-    SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
-    SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
-    SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
-    SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
-
-    static constexpr struct {
-      uint16_t Val;
-      unsigned IsReservedWhenSandboxing : 1;
-      unsigned Is64 : 1;
-      unsigned Is32 : 1;
-      unsigned Is16 : 1;
-      unsigned Is8 : 1;
-      unsigned IsXmm : 1;
-      unsigned Is64To8 : 1;
-      unsigned Is32To8 : 1;
-      unsigned Is16To8 : 1;
-      unsigned IsTrunc8Rcvr : 1;
-      unsigned IsAhRcvr : 1;
-#define NUM_ALIASES_BITS 2
-      SizeT NumAliases : (NUM_ALIASES_BITS + 1);
-      uint16_t Aliases[1 << NUM_ALIASES_BITS];
-#undef NUM_ALIASES_BITS
-    } X8664RegTable[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)                            \
-  {                                                                            \
-      RegisterSet::val,                                                        \
-      sboxres,                                                                 \
-      is64,                                                                    \
-      is32,                                                                    \
-      is16,                                                                    \
-      is8,                                                                     \
-      isXmm,                                                                   \
-      is64To8,                                                                 \
-      is32To8,                                                                 \
-      is16To8,                                                                 \
-      isTrunc8Rcvr,                                                            \
-      isAhRcvr,                                                                \
-      (SizeOf aliases).size(),                                                 \
-      aliases,                                                                 \
-  },
-        REGX8664_TABLE
-#undef X
-    };
-
-    for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) {
-      const auto &Entry = X8664RegTable[ii];
-      // Even though the register is disabled for register allocation, it might
-      // still be used by the Target Lowering (e.g., base pointer), so the
-      // register alias table still needs to be defined.
-      (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
-      for (Ice::SizeT J = 0; J < Entry.NumAliases; ++J) {
-        SizeT Alias = Entry.Aliases[J];
-        assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
-        (*RegisterAliases)[Entry.Val].set(Alias);
-      }
-
-      (*RegisterAliases)[Entry.Val].set(Entry.Val);
-
-      (IntegerRegistersI64)[Entry.Val] = Entry.Is64;
-      (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
-      (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
-      (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
-      (FloatRegisters)[Entry.Val] = Entry.IsXmm;
-      (VectorRegisters)[Entry.Val] = Entry.IsXmm;
-      (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
-      (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
-      (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
-      (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
-      (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
-    }
-
-    (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
-    (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
-    (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
-    (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
-    (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
-    (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64;
-    (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
-    (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
-    (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
-    (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
-    (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
-    (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
-    (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
-    (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
-    (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
-  }
-
-  static SmallBitVector getRegisterSet(const ::Ice::ClFlags &Flags,
-                                       TargetLowering::RegSetMask Include,
-                                       TargetLowering::RegSetMask Exclude) {
-    SmallBitVector Registers(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)                            \
-  if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
-    Registers[RegisterSet::val] = true;                                        \
-  if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
-    Registers[RegisterSet::val] = true;                                        \
-  if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
-    Registers[RegisterSet::val] = true;                                        \
-  if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
-    Registers[RegisterSet::val] = true;                                        \
-  if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
-    Registers[RegisterSet::val] = false;                                       \
-  if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
-    Registers[RegisterSet::val] = false;                                       \
-  if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
-    Registers[RegisterSet::val] = false;                                       \
-  if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
-    Registers[RegisterSet::val] = false;
-
-    REGX8664_TABLE
-
-#undef X
-
-    return Registers;
-  }
-
-  static RegNumT getRaxOrDie() { return RegisterSet::Reg_rax; }
-
-  static RegNumT getRdxOrDie() { return RegisterSet::Reg_rdx; }
-
-#if defined(_WIN64)
-  // Microsoft x86-64 calling convention:
-  //
-  // * The first four arguments of vector/fp type, regardless of their
-  // position relative to the other arguments in the argument list, are placed
-  // in registers %xmm0 - %xmm3.
-  //
-  // * The first four arguments of integer types, regardless of their position
-  // relative to the other arguments in the argument list, are placed in
-  // registers %rcx, %rdx, %r8, and %r9.
-
-  /// The maximum number of arguments to pass in XMM registers
-  static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
-  /// The maximum number of arguments to pass in GPR registers
-  static constexpr uint32_t X86_MAX_GPR_ARGS = 4;
-  static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
-    if (ArgNum >= X86_MAX_GPR_ARGS) {
-      return RegNumT();
-    }
-    static const RegisterSet::AllRegisters GprForArgNum[] = {
-        RegisterSet::Reg_rcx,
-        RegisterSet::Reg_rdx,
-        RegisterSet::Reg_r8,
-        RegisterSet::Reg_r9,
-    };
-    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 getGprForType(Ty, GprForArgNum[ArgNum]);
-  }
-  // Given the absolute argument position and argument position by type, return
-  // the register index to assign it to.
-  static SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
-    // Microsoft x64 ABI: register is selected by arg position (e.g. 1st int as
-    // 2nd param goes into 2nd int reg)
-    (void)argPosByType;
-    return argPos;
-  };
-
-#else
-  // System V x86-64 calling convention:
-  //
-  // * The first eight arguments of vector/fp type, regardless of their
-  // position relative to the other arguments in the argument list, are placed
-  // in registers %xmm0 - %xmm7.
-  //
-  // * The first six arguments of integer types, regardless of their position
-  // relative to the other arguments in the argument list, are placed in
-  // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
-  //
-  // This intends to match the section "Function Calling Sequence" of the
-  // document "System V Application Binary Interface."
-
-  /// The maximum number of arguments to pass in XMM registers
-  static constexpr uint32_t X86_MAX_XMM_ARGS = 8;
-  /// The maximum number of arguments to pass in GPR registers
-  static constexpr uint32_t X86_MAX_GPR_ARGS = 6;
-  /// 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();
-    }
-    static const RegisterSet::AllRegisters GprForArgNum[] = {
-        RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
-        RegisterSet::Reg_rcx, RegisterSet::Reg_r8,  RegisterSet::Reg_r9,
-    };
-    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 getGprForType(Ty, GprForArgNum[ArgNum]);
-  }
-  // Given the absolute argument position and argument position by type, return
-  // the register index to assign it to.
-  static SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
-    (void)argPos;
-    return argPosByType;
-  }
-#endif
-
-  /// 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 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 RegNumT();
-    }
-    return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
-  }
-
-  /// The number of bits in a byte
-  static constexpr uint32_t X86_CHAR_BIT = 8;
-  /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it
-  /// is used as an argument to std::max(), and the default std::less<T> has an
-  /// operator(T const&, T const&) which requires this member to have an
-  /// address.
-  static const uint32_t X86_STACK_ALIGNMENT_BYTES;
-  /// Size of the return address on the stack
-  static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8;
-  /// The number of different NOP instructions
-  static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
-
-  /// \name Limits for unrolling memory intrinsics.
-  /// @{
-  static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
-  static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
-  static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8;
-  /// @}
-
-  /// Value is in bytes. Return Value adjusted to the next highest multiple of
-  /// the stack alignment.
-  static uint32_t applyStackAlignment(uint32_t Value) {
-    return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
-  }
-
-  /// Return the type which the elements of the vector have in the X86
-  /// representation of the vector.
-  static Type getInVectorElementType(Type Ty) {
-    assert(isVectorType(Ty));
-    assert(Ty < TableTypeX8664AttributesSize);
-    return TableTypeX8664Attributes[Ty].InVectorElementType;
-  }
-
-  // Note: The following data structures are defined in
-  // IceTargetLoweringX8664.cpp.
-
-  /// The following table summarizes the logic for lowering the fcmp
-  /// instruction. There is one table entry for each of the 16 conditions.
-  ///
-  /// The first four columns describe the case when the operands are floating
-  /// point scalar values. A comment in lowerFcmp() describes the lowering
-  /// template. In the most general case, there is a compare followed by two
-  /// conditional branches, because some fcmp conditions don't map to a single
-  /// x86 conditional branch. However, in many cases it is possible to swap the
-  /// operands in the comparison and have a single conditional branch. Since
-  /// it's quite tedious to validate the table by hand, good execution tests are
-  /// helpful.
-  ///
-  /// The last two columns describe the case when the operands are vectors of
-  /// floating point values. For most fcmp conditions, there is a clear mapping
-  /// to a single x86 cmpps instruction variant. Some fcmp conditions require
-  /// special code to handle and these are marked in the table with a
-  /// Cmpps_Invalid predicate.
-  /// {@
-  static const struct TableFcmpType {
-    uint32_t Default;
-    bool SwapScalarOperands;
-    CondX86::BrCond C1, C2;
-    bool SwapVectorOperands;
-    CondX86::CmppsCond Predicate;
-  } TableFcmp[];
-  static const size_t TableFcmpSize;
-  /// @}
-
-  /// The following table summarizes the logic for lowering the icmp instruction
-  /// for i32 and narrower types. Each icmp condition has a clear mapping to an
-  /// x86 conditional branch instruction.
-  /// {@
-  static const struct TableIcmp32Type {
-    CondX86::BrCond Mapping;
-  } TableIcmp32[];
-  static const size_t TableIcmp32Size;
-  /// @}
-
-  /// The following table summarizes the logic for lowering the icmp instruction
-  /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
-  /// conditional branches are needed. For the other conditions, three separate
-  /// conditional branches are needed.
-  /// {@
-  static const struct TableIcmp64Type {
-    CondX86::BrCond C1, C2, C3;
-  } TableIcmp64[];
-  static const size_t TableIcmp64Size;
-  /// @}
-
-  static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
-    assert(Cond < TableIcmp32Size);
-    return TableIcmp32[Cond].Mapping;
-  }
-
-  static const struct TableTypeX8664AttributesType {
-    Type InVectorElementType;
-  } TableTypeX8664Attributes[];
-  static const size_t TableTypeX8664AttributesSize;
-};
-
-} // end of namespace X8664
-} // end of namespace Ice
-
-#endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H