[TableGen] Allow target specific flags for RegisterClass

Analogous to the TSFlags for machine instructions, this
patch introduces a bit vector for register classes to have
target specific flags that become a tablegened value in
TargetRegisterClass.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D108767
This commit is contained in:
Christudasan Devadasan 2021-08-26 09:42:06 -04:00
parent 89424a829f
commit 6a75041a16
6 changed files with 64 additions and 2 deletions

View File

@ -57,6 +57,8 @@ public:
/// 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

View File

@ -306,6 +306,9 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
// 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

View File

@ -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 <int size, list<ValueType> 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 */

View File

@ -734,7 +734,7 @@ static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
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<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
if (TypeList.empty())
@ -802,6 +802,12 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
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<BitInit>(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 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
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 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
});
AltOrderSelect = Super.AltOrderSelect;
AllocationPriority = Super.AllocationPriority;
TSFlags = Super.TSFlags;
GeneratePressureSet |= Super.GeneratePressureSet;
// Copy all allocation orders, filter out foreign registers from the larger

View File

@ -332,6 +332,7 @@ namespace llvm {
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.

View File

@ -1411,6 +1411,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< 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")