diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -57,6 +57,8 @@ /// Classes with a higher priority value are assigned first by register /// allocators using a greedy heuristic. The value is in the range [0,63]. const uint8_t AllocationPriority; + /// Configurable target specific flags. + const uint8_t TSFlags; /// Whether the class supports two (or more) disjunct subregister indices. const bool HasDisjunctSubRegs; /// Whether a combination of subregisters can cover every register in the diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -306,6 +306,9 @@ // the assembly matcher will provide a function to map from diagnostic types // to message strings. string DiagnosticString = ""; + + // Target-specific flags. This becomes the TSFlags field in TargetRegisterClass. + bits<8> TSFlags = 0; } // The memberList in a RegisterClass is a dag of set operations. TableGen diff --git a/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td b/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/RegisterInfoEmitter-tsflags.td @@ -0,0 +1,48 @@ +// RUN: llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s | FileCheck %s + +// Configure and test TSFlags for a target. +include "llvm/Target/Target.td" + +let Namespace = "MyTarget" in { + def R : Register<"r">; + def D : Register<"d">; + def S : Register<"s">; +} + +class MyClass types, dag regList> + : RegisterClass <"MyTarget", types, size, regList> { + // Define the target bitfields. + field bit A = 0; + field bits<2> B = 0; + + // Associate the defined bitfields to unique bit positions in TSFlags. + let TSFlags{0} = A; + let TSFlags{2-1} = B; +} + +// Default value for TSFlags. +def MyRegs : MyClass<32, [i32], (add R)>; + +def SRegs : MyClass<32, [i32], (add S)> { + let A = 1; +} + +def DRegs : MyClass<32, [i32], (add D)>{ + let B = 3; +} + +def SDRegs : MyClass<32, [i32], (add D, S)>{ + let A = 1; + let B = 3; +} + +def MyTarget : Target; + +// CHECK: extern const TargetRegisterClass SDRegsRegClass = { +// CHECK: 0x07, /* TSFlags */ +// CHECK: extern const TargetRegisterClass DRegsRegClass = { +// CHECK: 0x06, /* TSFlags */ +// CHECK: extern const TargetRegisterClass MyRegsRegClass = { +// CHECK: 0x00, /* TSFlags */ +// CHECK: extern const TargetRegisterClass SRegsRegClass = { +// CHECK: 0x01, /* TSFlags */ diff --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/CodeGenRegisters.h --- a/llvm/utils/TableGen/CodeGenRegisters.h +++ b/llvm/utils/TableGen/CodeGenRegisters.h @@ -332,6 +332,7 @@ bool Allocatable; StringRef AltOrderSelect; uint8_t AllocationPriority; + uint8_t TSFlags; /// Contains the combination of the lane masks of all subregisters. LaneBitmask LaneMask; /// True if there are at least 2 subregisters which do not interfere. diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp --- a/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -734,7 +734,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) : TheDef(R), Name(std::string(R->getName())), - TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1) { + TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), TSFlags(0) { GeneratePressureSet = R->getValueAsBit("GeneratePressureSet"); std::vector TypeList = R->getValueAsListOfDefs("RegTypes"); if (TypeList.empty()) @@ -802,6 +802,12 @@ if (AllocationPriority < 0 || AllocationPriority > 63) PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,63]"); this->AllocationPriority = AllocationPriority; + + BitsInit *TSF = R->getValueAsBitsInit("TSFlags"); + for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { + BitInit *Bit = cast(TSF->getBit(i)); + TSFlags |= uint8_t(Bit->getValue()) << i; + } } // Create an inferred register class that was missing from the .td files. @@ -811,7 +817,7 @@ StringRef Name, Key Props) : Members(*Props.Members), TheDef(nullptr), Name(std::string(Name)), TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), RSI(Props.RSI), - CopyCost(0), Allocatable(true), AllocationPriority(0) { + CopyCost(0), Allocatable(true), AllocationPriority(0), TSFlags(0) { Artificial = true; GeneratePressureSet = false; for (const auto R : Members) { @@ -839,6 +845,7 @@ }); AltOrderSelect = Super.AltOrderSelect; AllocationPriority = Super.AllocationPriority; + TSFlags = Super.TSFlags; GeneratePressureSet |= Super.GeneratePressureSet; // Copy all allocation orders, filter out foreign registers from the larger diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -1411,6 +1411,7 @@ << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "; printMask(OS, RC.LaneMask); OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n " + << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n " << (RC.HasDisjunctSubRegs?"true":"false") << ", /* HasDisjunctSubRegs */\n " << (RC.CoveredBySubRegs?"true":"false")