Index: include/llvm/MC/MCRegisterInfo.h =================================================================== --- include/llvm/MC/MCRegisterInfo.h +++ include/llvm/MC/MCRegisterInfo.h @@ -38,7 +38,9 @@ const uint16_t RegsSize; const uint16_t RegSetSize; const uint16_t ID; - const uint16_t RegSize, Alignment; // Size & Alignment of register in bytes + const uint16_t SpillSize; // Size (in bytes) of register spill slot. + const uint16_t Alignment; // Alignment (bytes) of register spill slot. + const uint16_t RegSize; // Register size (in bytes). const int8_t CopyCost; const bool Allocatable; @@ -77,14 +79,18 @@ return contains(Reg1) && contains(Reg2); } - /// getSize - Return the size of the register in bytes, which is also the size - /// of a stack slot allocated to hold a spilled copy of this register. - unsigned getSize() const { return RegSize; } + /// Return the size of a stack slot allocated to hold a spilled copy of + /// this register. + unsigned getSpillSize() const { return SpillSize; } + /// Same as above, present temporarily until all users are updated. + unsigned getSize() const { return SpillSize; } - /// getAlignment - Return the minimum required alignment for a register of - /// this class. + /// Return the minimum required alignment for a register of this class. unsigned getAlignment() const { return Alignment; } + /// Return the size of the register in bytes. + unsigned getRegSize() const { return RegSize; } + /// getCopyCost - Return the cost of copying a value between two registers in /// this class. A negative number means the register class is very expensive /// to copy e.g. status flag register classes. Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -164,15 +164,19 @@ // list RegTypes = regTypes; - // Size - Specify the spill size in bits of the registers. A default value of + // Specify the spill size in bits of the registers. A default value of // zero lets tablgen pick an appropriate size. - int Size = 0; + int SpillSize = 0; // Alignment - Specify the alignment required of the registers when they are // stored or loaded to memory. // int Alignment = alignment; + // Specify the register size in bits. A default value of zero will set it + // to the same value as SpillSize. + int RegSize = 0; + // CopyCost - This value is used to specify the cost of copying a value // between two registers in this register class. The default value is one // meaning it takes a single instruction to perform the copying. A negative Index: include/llvm/Target/TargetRegisterInfo.h =================================================================== --- include/llvm/Target/TargetRegisterInfo.h +++ include/llvm/Target/TargetRegisterInfo.h @@ -109,13 +109,18 @@ return MC->contains(Reg1, Reg2); } - /// Return the size of the register in bytes, which is also the size - /// of a stack slot allocated to hold a spilled copy of this register. + /// Return the size of a stack slot allocated to hold a spilled copy of + /// this register. + unsigned getSpillSize() const { return MC->getSpillSize(); } + /// Same as above, present temporarily until all users are updated. unsigned getSize() const { return MC->getSize(); } /// Return the minimum required alignment for a register of this class. unsigned getAlignment() const { return MC->getAlignment(); } + /// Return the size of the register in bytes. + unsigned getRegSize() const { return MC->getRegSize(); } + /// Return the cost of copying a value between two registers in this class. /// A negative number means the register class is very expensive /// to copy e.g. status flag register classes. Index: lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.td +++ lib/Target/AArch64/AArch64RegisterInfo.td @@ -387,10 +387,10 @@ } def FPR8 : RegisterClass<"AArch64", [untyped], 8, (sequence "B%u", 0, 31)> { - let Size = 8; + let SpillSize = 8; } def FPR16 : RegisterClass<"AArch64", [f16], 16, (sequence "H%u", 0, 31)> { - let Size = 16; + let SpillSize = 16; } def FPR32 : RegisterClass<"AArch64", [f32, i32], 32,(sequence "S%u", 0, 31)>; def FPR64 : RegisterClass<"AArch64", [f64, i64, v2f32, v1f64, v8i8, v4i16, v2i32, @@ -419,13 +419,13 @@ [(rotl FPR64, 0), (rotl FPR64, 1), (rotl FPR64, 2), (rotl FPR64, 3)]>; def DD : RegisterClass<"AArch64", [untyped], 64, (add DSeqPairs)> { - let Size = 128; + let SpillSize = 128; } def DDD : RegisterClass<"AArch64", [untyped], 64, (add DSeqTriples)> { - let Size = 196; + let SpillSize = 196; } def DDDD : RegisterClass<"AArch64", [untyped], 64, (add DSeqQuads)> { - let Size = 256; + let SpillSize = 256; } // Pairs, triples, and quads of 128-bit vector registers. @@ -437,13 +437,13 @@ [(rotl FPR128, 0), (rotl FPR128, 1), (rotl FPR128, 2), (rotl FPR128, 3)]>; def QQ : RegisterClass<"AArch64", [untyped], 128, (add QSeqPairs)> { - let Size = 256; + let SpillSize = 256; } def QQQ : RegisterClass<"AArch64", [untyped], 128, (add QSeqTriples)> { - let Size = 384; + let SpillSize = 384; } def QQQQ : RegisterClass<"AArch64", [untyped], 128, (add QSeqQuads)> { - let Size = 512; + let SpillSize = 512; } @@ -609,11 +609,11 @@ def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32, (add WSeqPairs)>{ - let Size = 64; + let SpillSize = 64; } def XSeqPairsClass : RegisterClass<"AArch64", [untyped], 64, (add XSeqPairs)>{ - let Size = 128; + let SpillSize = 128; } Index: lib/Target/AMDGPU/SIRegisterInfo.td =================================================================== --- lib/Target/AMDGPU/SIRegisterInfo.td +++ lib/Target/AMDGPU/SIRegisterInfo.td @@ -312,7 +312,7 @@ } def VReg_96 : RegisterClass<"AMDGPU", [untyped], 32, (add VGPR_96)> { - let Size = 96; + let SpillSize = 96; // Requires 3 v_mov_b32 to copy let CopyCost = 3; @@ -336,7 +336,7 @@ } def VReg_1 : RegisterClass<"AMDGPU", [i1], 32, (add VGPR_32)> { - let Size = 32; + let SpillSize = 32; } def VS_32 : RegisterClass<"AMDGPU", [i32, f32], 32, (add VGPR_32, SReg_32)>; Index: lib/Target/ARM/ARMRegisterInfo.td =================================================================== --- lib/Target/ARM/ARMRegisterInfo.td +++ lib/Target/ARM/ARMRegisterInfo.td @@ -351,7 +351,7 @@ // Register class representing a pair of even-odd GPRs. def GPRPair : RegisterClass<"ARM", [untyped], 64, (add Tuples2R)> { - let Size = 64; // 2 x 32 bits, we have no predefined type of that size. + let SpillSize = 64; // 2 x 32 bits, we have no predefined type of that size. } // Pseudo-registers representing 3 consecutive D registers. @@ -362,7 +362,7 @@ // 3 consecutive D registers. def DTriple : RegisterClass<"ARM", [untyped], 64, (add Tuples3D)> { - let Size = 192; // 3 x 64 bits, we have no predefined type of that size. + let SpillSize = 192; // 3 x 64 bits, we have no predefined type of that size. } // Pseudo 256-bit registers to represent pairs of Q registers. These should @@ -417,7 +417,7 @@ // Spaced triples of D registers. def DTripleSpc : RegisterClass<"ARM", [untyped], 64, (add Tuples3DSpc)> { - let Size = 192; // 3 x 64 bits, we have no predefined type of that size. + let SpillSize = 192; // 3 x 64 bits, we have no predefined type of that size. } def Tuples4DSpc : RegisterTuples<[dsub_0, dsub_2, dsub_4, dsub_6], Index: lib/Target/Hexagon/HexagonRegisterInfo.td =================================================================== --- lib/Target/Hexagon/HexagonRegisterInfo.td +++ lib/Target/Hexagon/HexagonRegisterInfo.td @@ -244,24 +244,22 @@ def VecPredRegs128B : RegisterClass<"Hexagon", [v1024i1], 1024, (add (sequence "Q%u", 0, 3))>; +let SpillSize = 32 in def PredRegs : RegisterClass<"Hexagon", [i1, v2i1, v4i1, v8i1, v4i8, v2i16, i32], 32, - (add (sequence "P%u", 0, 3))> -{ - let Size = 32; -} + (add (sequence "P%u", 0, 3))>; -let Size = 32 in +let SpillSize = 32 in def ModRegs : RegisterClass<"Hexagon", [i32], 32, (add M0, M1)>; -let Size = 32, isAllocatable = 0 in +let SpillSize = 32, isAllocatable = 0 in def CtrRegs : RegisterClass<"Hexagon", [i32], 32, (add LC0, SA0, LC1, SA1, P3_0, M0, M1, C6, C7, CS0, CS1, UPCL, UPCH, USR, USR_OVF, UGP, GP, PC)>; -let Size = 64, isAllocatable = 0 in +let SpillSize = 64, isAllocatable = 0 in def CtrRegs64 : RegisterClass<"Hexagon", [i64], 64, (add C1_0, C3_2, C7_6, C9_8, C11_10, CS, UPC)>; Index: lib/Target/Mips/MipsRegisterInfo.td =================================================================== --- lib/Target/Mips/MipsRegisterInfo.td +++ lib/Target/Mips/MipsRegisterInfo.td @@ -428,15 +428,15 @@ // Accumulator Registers def ACC64 : RegisterClass<"Mips", [untyped], 64, (add AC0)> { - let Size = 64; + let SpillSize = 64; } def ACC128 : RegisterClass<"Mips", [untyped], 128, (add AC0_64)> { - let Size = 128; + let SpillSize = 128; } def ACC64DSP : RegisterClass<"Mips", [untyped], 64, (sequence "AC%u", 0, 3)> { - let Size = 64; + let SpillSize = 64; } def DSPCC : RegisterClass<"Mips", [v4i8, v2i16], 32, (add DSPCCond)>; Index: lib/Target/PowerPC/PPCRegisterInfo.td =================================================================== --- lib/Target/PowerPC/PPCRegisterInfo.td +++ lib/Target/PowerPC/PPCRegisterInfo.td @@ -326,7 +326,7 @@ def QBRC : RegisterClass<"PPC", [v4i1], 256, (add QFRC)> { // These are actually stored as floating-point values where a positive // number is true and anything else (including NaN) is false. - let Size = 256; + let SpillSize = 256; } def CRBITRC : RegisterClass<"PPC", [i1], 32, @@ -338,7 +338,7 @@ CR7LT, CR7GT, CR7EQ, CR7UN, CR1LT, CR1GT, CR1EQ, CR1UN, CR0LT, CR0GT, CR0EQ, CR0UN)> { - let Size = 32; + let SpillSize = 32; } def CRRC : RegisterClass<"PPC", [i32], 32, (add CR0, CR1, CR5, CR6, Index: lib/Target/SystemZ/SystemZRegisterInfo.td =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.td +++ lib/Target/SystemZ/SystemZRegisterInfo.td @@ -35,15 +35,15 @@ // Define a register class that contains values of types TYPES and an // associated operand called NAME. SIZE is the size and alignment // of the registers and REGLIST is the list of individual registers. -multiclass SystemZRegClass types, int size, +multiclass SystemZRegClass types, int spillSize, dag regList> { def AsmOperand : AsmOperandClass { let Name = name; let ParserMethod = "parse"##name; let RenderMethod = "addRegOperands"; } - def Bit : RegisterClass<"SystemZ", types, size, regList> { - let Size = size; + def Bit : RegisterClass<"SystemZ", types, spillSize, regList> { + let SpillSize = spillSize; } def "" : RegisterOperand(name##"Bit")> { let ParserMatchClass = !cast(name##"AsmOperand"); Index: lib/Target/X86/X86RegisterInfo.td =================================================================== --- lib/Target/X86/X86RegisterInfo.td +++ lib/Target/X86/X86RegisterInfo.td @@ -508,21 +508,21 @@ 256, (sequence "YMM%u", 0, 31)>; // Mask registers -def VK1 : RegisterClass<"X86", [i1], 16, (sequence "K%u", 0, 7)> {let Size = 16;} -def VK2 : RegisterClass<"X86", [v2i1], 16, (add VK1)> {let Size = 16;} -def VK4 : RegisterClass<"X86", [v4i1], 16, (add VK2)> {let Size = 16;} -def VK8 : RegisterClass<"X86", [v8i1], 16, (add VK4)> {let Size = 16;} -def VK16 : RegisterClass<"X86", [v16i1], 16, (add VK8)> {let Size = 16;} -def VK32 : RegisterClass<"X86", [v32i1], 32, (add VK16)> {let Size = 32;} -def VK64 : RegisterClass<"X86", [v64i1], 64, (add VK32)> {let Size = 64;} - -def VK1WM : RegisterClass<"X86", [i1], 16, (sub VK1, K0)> {let Size = 16;} -def VK2WM : RegisterClass<"X86", [v2i1], 16, (sub VK2, K0)> {let Size = 16;} -def VK4WM : RegisterClass<"X86", [v4i1], 16, (sub VK4, K0)> {let Size = 16;} -def VK8WM : RegisterClass<"X86", [v8i1], 16, (sub VK8, K0)> {let Size = 16;} -def VK16WM : RegisterClass<"X86", [v16i1], 16, (add VK8WM)> {let Size = 16;} -def VK32WM : RegisterClass<"X86", [v32i1], 32, (add VK16WM)> {let Size = 32;} -def VK64WM : RegisterClass<"X86", [v64i1], 64, (add VK32WM)> {let Size = 64;} +def VK1 : RegisterClass<"X86", [i1], 16, (sequence "K%u", 0, 7)> {let SpillSize = 16;} +def VK2 : RegisterClass<"X86", [v2i1], 16, (add VK1)> {let SpillSize = 16;} +def VK4 : RegisterClass<"X86", [v4i1], 16, (add VK2)> {let SpillSize = 16;} +def VK8 : RegisterClass<"X86", [v8i1], 16, (add VK4)> {let SpillSize = 16;} +def VK16 : RegisterClass<"X86", [v16i1], 16, (add VK8)> {let SpillSize = 16;} +def VK32 : RegisterClass<"X86", [v32i1], 32, (add VK16)> {let SpillSize = 32;} +def VK64 : RegisterClass<"X86", [v64i1], 64, (add VK32)> {let SpillSize = 64;} + +def VK1WM : RegisterClass<"X86", [i1], 16, (sub VK1, K0)> {let SpillSize = 16;} +def VK2WM : RegisterClass<"X86", [v2i1], 16, (sub VK2, K0)> {let SpillSize = 16;} +def VK4WM : RegisterClass<"X86", [v4i1], 16, (sub VK4, K0)> {let SpillSize = 16;} +def VK8WM : RegisterClass<"X86", [v8i1], 16, (sub VK8, K0)> {let SpillSize = 16;} +def VK16WM : RegisterClass<"X86", [v16i1], 16, (add VK8WM)> {let SpillSize = 16;} +def VK32WM : RegisterClass<"X86", [v32i1], 32, (add VK16WM)> {let SpillSize = 32;} +def VK64WM : RegisterClass<"X86", [v64i1], 64, (add VK32WM)> {let SpillSize = 64;} // Bound registers def BNDR : RegisterClass<"X86", [v2i64], 128, (sequence "BND%u", 0, 3)>; Index: utils/TableGen/CodeGenRegisters.h =================================================================== --- utils/TableGen/CodeGenRegisters.h +++ utils/TableGen/CodeGenRegisters.h @@ -302,6 +302,10 @@ SmallVector VTs; unsigned SpillSize; unsigned SpillAlignment; + // The member RegSize does not participate in the calculation of the RC + // properties and relations. It only serves to provide register size to + // MCRegisterClass. + unsigned RegSize; int CopyCost; bool Allocatable; std::string AltOrderSelect; @@ -406,14 +410,17 @@ const CodeGenRegister::Vec *Members; unsigned SpillSize; unsigned SpillAlignment; + unsigned RegSize; - Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0) - : Members(M), SpillSize(S), SpillAlignment(A) {} + Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0, + unsigned R = 0) + : Members(M), SpillSize(S), SpillAlignment(A), RegSize(R) {} Key(const CodeGenRegisterClass &RC) : Members(&RC.getMembers()), SpillSize(RC.SpillSize), - SpillAlignment(RC.SpillAlignment) {} + SpillAlignment(RC.SpillAlignment), + RegSize(RC.RegSize) {} // Lexicographical order of (Members, SpillSize, SpillAlignment). bool operator<(const Key&) const; Index: utils/TableGen/CodeGenRegisters.cpp =================================================================== --- utils/TableGen/CodeGenRegisters.cpp +++ utils/TableGen/CodeGenRegisters.cpp @@ -702,11 +702,13 @@ } // Allow targets to override the size in bits of the RegisterClass. - unsigned Size = R->getValueAsInt("Size"); + unsigned SSize = R->getValueAsInt("SpillSize"); + unsigned RSize = R->getValueAsInt("RegSize"); Namespace = R->getValueAsString("Namespace"); - SpillSize = Size ? Size : MVT(VTs[0]).getSizeInBits(); + SpillSize = SSize ? SSize : MVT(VTs[0]).getSizeInBits(); SpillAlignment = R->getValueAsInt("Alignment"); + RegSize = RSize ? RSize : SpillSize; CopyCost = R->getValueAsInt("CopyCost"); Allocatable = R->getValueAsBit("isAllocatable"); AltOrderSelect = R->getValueAsString("AltOrderSelect"); @@ -728,6 +730,7 @@ EnumValue(-1), SpillSize(Props.SpillSize), SpillAlignment(Props.SpillAlignment), + RegSize(Props.RegSize), CopyCost(0), Allocatable(true), AllocationPriority(0) { @@ -768,7 +771,8 @@ namespace llvm { raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) { - OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment; + OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment + << ", R=" << K.RegSize; for (const auto R : *K.Members) OS << ", " << R->getName(); return OS << " }"; @@ -780,8 +784,8 @@ bool CodeGenRegisterClass::Key:: operator<(const CodeGenRegisterClass::Key &B) const { assert(Members && B.Members); - return std::tie(*Members, SpillSize, SpillAlignment) < - std::tie(*B.Members, B.SpillSize, B.SpillAlignment); + return std::tie(*Members, SpillSize, SpillAlignment, RegSize) < + std::tie(*B.Members, B.SpillSize, B.SpillAlignment, B.RegSize); } // Returns true if RC is a strict subclass. @@ -795,6 +799,7 @@ // static bool testSubClass(const CodeGenRegisterClass *A, const CodeGenRegisterClass *B) { + // Ignore RegSize. return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 && A->SpillSize <= B->SpillSize && std::includes(A->getMembers().begin(), A->getMembers().end(), @@ -827,6 +832,8 @@ if (A->SpillAlignment > B->SpillAlignment) return false; + // Ignore RegSize. + // Order by descending set size. Note that the classes' allocation order may // not have been computed yet. The Members set is always vaild. if (A->getMembers().size() > B->getMembers().size()) @@ -1049,7 +1056,8 @@ const CodeGenRegister::Vec *Members, StringRef Name) { // Synthetic sub-class has the same size and alignment as RC. - CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment); + CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment, + RC->RegSize); RCKeyMap::const_iterator FoundI = Key2RC.find(K); if (FoundI != Key2RC.end()) return FoundI->second; Index: utils/TableGen/RegisterInfoEmitter.cpp =================================================================== --- utils/TableGen/RegisterInfoEmitter.cpp +++ utils/TableGen/RegisterInfoEmitter.cpp @@ -1031,6 +1031,7 @@ // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); + assert((RC.RegSize/8) <= 0xffff && "RegSize too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " @@ -1039,6 +1040,7 @@ << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " + << RC.RegSize/8 << ", " << RC.CopyCost << ", " << ( RC.Allocatable ? "true" : "false" ) << " },\n"; }