[llvm] TableGen support for RegisterBankInfo (PR #71357)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 11 22:20:21 PST 2023


================
@@ -289,6 +299,138 @@ void RegisterBankEmitter::emitBaseClassImplementation(
      << "} // end namespace llvm\n";
 }
 
+// This emitter generates PartialMappings, PartialMappingIdx,
+// BankIDToCopyMapIdx and BankIDToRegisterClassCount from the .td files.
+// However it requires that the .td files fully describe their RegisterBanks
+// and otherwise emits #error lines for the offending Registers.
+//
+// These tables and enums are enabled by GET_REGBANKINFO_DECLARATIONS,
+// GET_REGBANKINFO_PARTIALMAPPINGS and GET_REGBANKINFO_VALUEMAPPINGS
+// So a backend which doesn't fully describe its RegisterBanks
+// will not break if it doesn't define these macros.
+//
+// This was discussed in https://discourse.llvm.org/t/74459
+void RegisterBankEmitter::emitRBIHeader(
+    raw_ostream &OS, StringRef TargetName,
+    const std::vector<RegisterBank> &Banks) {
+  const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
+
+  OS << "namespace llvm {\n"
+     << "namespace " << TargetName << " {\n"
+     << "enum PartialMappingIdx {\n"
+     << "  PMI_None = -1,\n";
+
+  // Banks and Register Classes are *not* emitted in their original text order
+  int ID = 0;
+  for (const auto &Bank : Banks) {
+    for (const CodeGenRegisterClass *RC :
+         Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+      OS << "  PMI_" << RC->getName() << " = " << ID++ << ",\n";
----------------
topperc wrote:

I'm well aware that everything is inconsistent. I'm trying to explain what I believe AArch64 intended when they started this project.

I believe the intent of the register class lists in *RegisterBanks.td was to allow targets to list the minimum number of register classes to allow tablegen to find the rest of the related to registers. This is why RISC-V uses FPR64 only and AArch64 uses QQQQ. Those are the largest super classes that the FPR registers on those targets belong to. Tablegen can walk down the subregister information from there and find all of the register classes that need to belong to the bank. This is expressed in the CoverageData table. The type lists on the register classes should have nothing to do with this.

The union of the sizes from all of the covered register classes should be used to fill in the partial mapping table. Tblgen infers that the FPR register bank for RISC-V includes the following register classes

```
const uint32_t FPRRegBankCoverageData[] = {                                      
    // 0-31                                                                      
    (1u << (RISCV::FPR64RegClassID - 0)) |                                       
    (1u << (RISCV::FPR16RegClassID - 0)) |                                       
    (1u << (RISCV::FPR32RegClassID - 0)) |                                       
    (1u << (RISCV::FPR64CRegClassID - 0)) |                                      
    (1u << (RISCV::FPR32CRegClassID - 0)) |                                      
    0,                                                                           
    // 32-63                                                                     
    0,                                                                           
    // 64-95                                                                     
    0,                                                                           
};
```

Examining the sizes of those 6 register classes will reveal 3 unique sizes, 16, 32, and 64. So RISC-V should have PMI_FPR16, PMI_FPR32, and PMI_FPR64 as partial mapping indices for the FPR bank. I'm aware that PMI_FPR16 is missing today. I will add it soon.

For GPR on RISC-V we there are many register classes but they all have the same sizes which comes from HwMode. I think we should walk through all of the register classes in `GPRRegBankCoverageData` and for each class look at the possible sizes HwMode gives for them. They should all give the same two values, 32 and 64. So we should have PMI_GPR32 and PMI_GPR64.

On AArch64, FPRRegBankCoverageData contains a bunch of register classes inferred by QQQQ. I bet if we check the sizes of the all of those classes we will find sizes 8, 16, 32, 64, 128, 256, and 512. All of the sizes for FPR in AArch64's partial mapping index for FPR. Except 8 which I think is just missing from GlobalISel.

https://github.com/llvm/llvm-project/pull/71357


More information about the llvm-commits mailing list