td中RegisterClass的使用和定義

RegisterInfo.td中RegisterClass的使用和定義

在 LLVM TableGen 中,RegisterClass 是用于定義寄存器類的基本類,其通用語法為:

def ClassName : RegisterClass<"Namespace", [ValueType], Size, RegisterList> {
  // 可選屬性
  let Property1 = Value1;
  let Property2 = Value2;
  // ...
}
  • "Namespace": 寄存器類的命名空間,通常是目標(biāo)架構(gòu)名稱,比如:"ARM","Lanai"
  • Size: 寄存器的大小(以位為單位),比如:32
  • RegisterList: 寄存器列表,定義了寄存器類包含的寄存器及其分配順序,可以是(sequence "R%u", 0, 12)定義的一些列的列表或者手動(dòng)指定的寄存器。
    后面的let中可以添加自定義的屬性,并設(shè)置值。

GPR(通用寄存器類),通用寄存器的主要作用包括:

寄存器分配:為寄存器分配器提供可用的寄存器池和分配順序
指令選擇:幫助指令選擇器確定哪些寄存器可以用于特定指令
約束處理:處理內(nèi)聯(lián)匯編中的寄存器約束
代碼生成:指導(dǎo)代碼生成器如何使用寄存器
調(diào)試信息:為調(diào)試信息生成提供寄存器信息

定義 GPR 的方法包括:

  • 直接列出寄存器:如 (add R0, R1, R2, ...)
  • 使用序列生成:如 (sequence "R%u", 0, 12) 生成 R0 到 R12
  • 組合使用:如 (add (sequence "R%u", 0, 12), SP, LR, PC)
    使用操作符:
    add: 添加寄存器到列表
    trunc: 截?cái)嗉拇嫫髁斜?br> shl: 左移寄存器列表
    sequence: 生成寄存器序列

let 可以用于設(shè)置多種屬性

是可選的,屬性的數(shù)量沒有限制,常見的有:

  • Size: 寄存器大小(以位為單位)
    let Size = 32;
  • CopyCost: 復(fù)制寄存器的成本
    let CopyCost = -1; // -1 表示不允許復(fù)制
  • isAllocatable: 是否可分配
    let isAllocatable = 0; // 0 表示不可分配
  • AltOrders: 替代的寄存器分配順序
    let AltOrders = [(add LR, GPR), (trunc GPR, 8), ...];
  • AltOrderSelect: 選擇替代分配順序的函數(shù)
    let AltOrderSelect = [{
    return MF.getSubtarget<ARMSubtarget>().getGPRAllocationOrder(MF);
    }];
  • DiagnosticString: 診斷字符串
    let DiagnosticString = "operand must be a register in range [r0, r15]";
  • RegInfos: 寄存器信息
    let RegInfos = GRLenRI;
    這些屬性的具體值和可用性取決于目標(biāo)架構(gòu)和 LLVM 后端的實(shí)現(xiàn)。不同的架構(gòu)可能支持不同的屬性,或者對(duì)同一屬性有不同的解釋。

示例1

def GPR : GPRRegisterClass<(add (sequence "X%u", 10, 17),
                                (sequence "X%u", 5, 7),
                                (sequence "X%u", 28, 31),
                                (sequence "X%u", 8, 9),
                                (sequence "X%u", 18, 27),
                                (sequence "X%u", 0, 4))>;

這個(gè)定義使用了自定義的 GPRRegisterClass 類(不是標(biāo)準(zhǔn)的 RegisterClass),它通過多個(gè) sequence 指定了寄存器的分配順序。
沒有指定架構(gòu),每個(gè) sequence "X%u", Start, End 生成從 XStart 到 XEnd 的寄存器序列。
這個(gè)等價(jià)的生成C++代碼是什么,這幾個(gè)sequence的順序有什么約定嗎?

示例2

def GPR : RegisterClass<"LoongArch", [GRLenVT], 32, (add
    // Argument registers (a0...a7)
    (sequence "R%u", 4, 11),
    // Temporary registers (t0...t8)
    (sequence "R%u", 12, 20),
    // Static register (s9/fp, s0...s8)
    (sequence "R%u", 22, 31),
    // Specials (r0, ra, tp, sp)
    (sequence "R%u", 0, 3),
    // Reserved (Non-allocatable)
    R21
  )> {
  let RegInfos = GRLenRI;
}

命名空間為 "LoongArch"
可以保存 GRLenVT 類型的值(可能是根據(jù)架構(gòu)定義的變量類型)
寄存器大小為 32 位
按照功能分組寄存器:參數(shù)寄存器、臨時(shí)寄存器、靜態(tài)寄存器、特殊寄存器和保留寄存器
添加了 RegInfos 屬性,值為 GRLenRI(可能是與寄存器信息相關(guān)的定義)

示例3

def GPR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12),
                                               SP, LR, PC)> {
  let AltOrders = [(add LR, GPR), (trunc GPR, 8),
                   (add (trunc GPR, 8), R12, LR, (shl GPR, 8))];
  let AltOrderSelect = [{
      return MF.getSubtarget<ARMSubtarget>().getGPRAllocationOrder(MF);
  }];
  let DiagnosticString = "operand must be a register in range [r0, r15]";
}

包含從 R0 到 R12 的寄存器,以及 SP(堆棧指針)、LR(鏈接寄存器)和 PC(程序計(jì)數(shù)器)
定義了 AltOrders 和 AltOrderSelect 屬性,用于根據(jù)不同的子目標(biāo)選擇不同的寄存器分配順序
添加了 DiagnosticString 屬性,用于在寄存器使用不當(dāng)時(shí)提供錯(cuò)誤信息

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容