AMDGPU 后端 ABI 总览
适用范围 :
llvm/lib/Target/AMDGPU(GCN/SI 及以后,GCNSubtarget)
CPU ABI 参考(可选) :llvm/lib/Target/X86/X86CallingConv.td(如CC_X86_64_C)
目录
- [什么是后端 ABI](#什么是后端 ABI)
- [ABI 七个维度](#ABI 七个维度)
- [多套并行 ABI](#多套并行 ABI)
- [Part A --- Device/Leaf 可调用 ABI](#Part A — Device/Leaf 可调用 ABI)
- [Part B --- Kernel(Compute)入口 ABI](#Part B — Kernel(Compute)入口 ABI)
- [Part C --- Graphics 与其它 CC](#Part C — Graphics 与其它 CC)
- 编译流水线与分工
- 调试与源文件
1. 什么是后端 ABI
ABI 规定二进制层面函数如何传参、返回、保存寄存器、使用栈/scratch,以及 kernel 如何与 runtime(ROCm/HSA/PAL)对接。
AMDGPU 后端实现分散在:
| 组件 | 路径 |
|---|---|
| TableGen CC/CSR | AMDGPUCallingConv.td |
| 寄存器与 RegMask | SIRegisterInfo.cpp |
| ISel 传参 | SIISelLowering.cpp、AMDGPUISelLowering.cpp |
| 栈帧 / PEI | SIFrameLowering.cpp、SILowerSGPRSpills.cpp |
| Clang | clang/lib/CodeGen/Targets/AMDGPU.cpp |
Compute kernel 参数主要来自 kernarg segment(常量缓冲区) ,由 kernarg segment pointer(User SGPR) 间接访问,而非像 x86 SysV 那样由 caller 在 CALL 前写入 RDI/RSI/栈传参。
2. ABI 的七个维度
| # | 维度 | AMDGPU 要点 |
|---|---|---|
| 1 | 数据布局 | AMDGPUTargetMachine::computeDataLayout():多地址空间(p1 global、p3 shared、p5 private 等);ni:7:8:9 非整型 buffer 指针 |
| 2 | CallingConv ID | AMDGPU_KERNEL(91)、C/Fast/Cold、AMDGPU_Gfx、AMDGPU_PS/VS/...、AMDGPU_CS_Chain 等 |
| 3 | 参数/返回 | Leaf:CC_AMDGPU_Func;SI shader:CC_SI_SHADER;Kernel:analyzeFormalArgumentsCompute → Mem/custom |
| 4 | 寄存器保存 | 条纹 CSR:CSR_AMDGPU_VGPRs + CSR_AMDGPU_SGPRs;GFX90A+ 含 CSR_AMDGPU_AGPRs |
| 5 | 栈帧 | Scratch (通过 buffer resource SGPR + 私有指针);非传统 CPU 栈;s32 常作 stack pointer |
| 6 | 寄存器约束 | 大量 reserved SGPR(VCC、flat scratch、kernarg ptr 等);WWM/spill 专用 VGPR |
| 7 | 运行时 | PIC 强制;HSA code object、amd_kernel_code_t、PAL metadata |
3. 多套并行 ABI
| 轨道 | CallingConv | 典型来源 | 参数通道 | 返回值 |
|---|---|---|---|---|
| Compute Kernel | AMDGPU_KERNEL / SPIR_KERNEL |
OpenCL __kernel、HIP __global__ |
Kernarg buffer(+ User SGPR) | 通常 void |
| Device/Leaf | C / Fast / Cold → CC_AMDGPU_Func |
HIP device 函数、内部 leaf | VGPR0-31 / SGPR0-29(inreg)+ 栈 |
VGPR0-31 |
| SI Shader(非 SI 以前) | CC_AMDGPU → CC_SI_SHADER |
部分 legacy 路径 | SGPR0-43 / VGPR0-135 |
RetCC_SI_Shader |
| AMDGPU_Gfx | AMDGPU_Gfx |
Gfx pipeline | CC_SI_Gfx(SGPR4-29 / VGPR) |
RetCC_SI_Gfx |
| Graphics 固定管线 | AMDGPU_PS/VS/GS/... |
图形着色器 | 专用输入分配 + PS 插值 | 管线相关 |
| CS Chain | AMDGPU_CS_Chain |
Mesh shader 链 | CC_AMDGPU_CS_CHAIN |
常不返回 |
与 X86(SysV x86-64)对照(速记)
X86-64(CC_X86_64_C) |
AMDGPU | |
|---|---|---|
| 整数传参 | RDI, RSI, RDX, RCX, R8, R9 + 栈 |
VGPR0-31 / SGPR0-29(inreg)+ 栈/scratch |
| 返回值 | RAX(+ RDX 等) |
VGPR0-31 |
| Callee-saved | RBX, RBP, R12-R15 等 |
条纹 CSR_AMDGPU_VGPRs + CSR_AMDGPU_SGPRs |
| 栈指针 | RSP |
s32 + Scratch 资源 |
| GPU Kernel | (无对应 IR CC) | AMDGPU_KERNEL + kernarg buffer |
Part A --- Device/Leaf 可调用 ABI
A.1 TableGen:CC_AMDGPU_Func / RetCC_AMDGPU_Func
tablegen
// AMDGPUCallingConv.td(摘要)
def CC_AMDGPU_Func : CallingConv<[
CCIfByVal<CCPassByVal<4, 4>>,
CCIfInReg<... CCAssignToReg<SGPR0..29>>,
CCIfType<... CCAssignToReg<VGPR0..31>>,
CCAssignToStack<4, 4>
]>;
def RetCC_AMDGPU_Func : CallingConv<[
CCAssignToReg<VGPR0..31>
]>;
inreg属性 :标量/小向量走 SGPR ;否则默认 VGPR。- 聚合 ≤16 个 32 位寄存器可直接传递(Clang
MaxNumRegsForArgsRet = 16)。
A.2 CC_AMDGPU 路由(SI+)
tablegen
def CC_AMDGPU : CallingConv<[
CCIf<"... SI+ ...", CCDelegateTo<CC_SI_SHADER>>,
CCIf<"... SI+ && CC==C", CCDelegateTo<CC_AMDGPU_Func>>
]>;
实际 device 互调多走 C → CC_AMDGPU_Func。
A.3 Callee-saved(条纹 CSR)
tablegen
def CSR_AMDGPU : CalleeSavedRegs<(add CSR_AMDGPU_VGPRs, CSR_AMDGPU_SGPRs)>;
// GFX90A+:CSR_AMDGPU_GFX90AInsts 另加 CSR_AMDGPU_AGPRs
| 集合 | 模式 | 说明 |
|---|---|---|
CSR_AMDGPU_VGPRs |
VGPR40-47, 56-63, ... 多段 |
条纹 callee-saved VGPR |
CSR_AMDGPU_SGPRs |
SGPR30-39, 48-55, ... |
含 s30-s31 返回地址、s32 SP 等 |
CSR_AMDGPU_SI_Gfx |
不同 SGPR 范围 | AMDGPU_Gfx 专用 |
getCalleeSavedRegs / getCallPreservedMask(SIRegisterInfo.cpp)对 C/Fast/Cold 返回 CSR_AMDGPU_*;AMDGPU_KERNEL 返回空表 (仅 NoRegister 占位)。
A.4 Caller/Callee 两张表
| 机制 | 产物 | 阶段 |
|---|---|---|
CalleeSavedRegs |
CSR_AMDGPU_*_SaveList |
PEI(VGPR + 独立 SGPR pass) |
getCallPreservedMask |
CSR_AMDGPU_*_RegMask |
Regalloc 跨 call |
A.5 MustSpill
与 X86 等目标相同(LLVM 通用语义):跨 call 仍 live 且 RegMask clobbered → caller spill。
Leaf ABI 下 VGPR0-31 为 caller-save;条纹 CSR 内寄存器为 preserved(类比 x86 上 RAX/RCX 等为 caller-save、RBX/R12 等为 callee-save)。
Part B --- Kernel(Compute)入口 ABI
B.1 核心概念
- IR:
CallingConv::AMDGPU_KERNEL(91)或SPIR_KERNEL。 - 所有 kernel 实参在逻辑上位于 kernarg segment(常量/全局 buffer),不是 SGPR/VGPR 直接传值。
- Clang:
classifyKernelArgumentType→ 聚合getIndirectAliased(opencl_constant)或getDirect;HIP 可将指针 coerce 到 global AS。
B.2 analyzeFormalArgumentsCompute
(AMDGPUISelLowering.cpp)
- 按
Function::args()重新计算 对齐后的字节偏移 (ExplicitKernelArgOffset)。 - 每个参数拆分为若干
CCValAssign::CustomMem(InIndex、BasePartOffset、MemVT)。 - 不 使用
CC_AMDGPU_Func的寄存器分配表。
B.3 LowerFormalArguments(Kernel 分支)
(SIISelLowering.cpp)
IsKernel→analyzeFormalArgumentsCompute(CCInfo, Ins)allocateSpecialEntryInputVGPRs/allocateHSAUserSGPRs(workgroup ID、dispatch ptr、kernarg segment ptr 等)- 可选
allocatePreloadKernArgSGPRs(hasKernargPreload) - 从 kernarg 地址 load 到 VGPR(kernel 参数在 IR 层视为 SGPR 源,实际 load 到向量寄存器使用)
B.4 隐式 SGPR(HSA)
Entry kernel 由 runtime 填入的 User SGPR 包括(视 subtarget/OS 而定):
- Workgroup / workitem ID
- Kernarg segment pointer
- Dispatch pointer、queue pointer(code object v5)
- Private segment wave buffer、flat scratch init 等
详见 allocateHSAUserSGPRs、SIMachineFunctionInfo。
B.5 返回值与 PEI
- Kernel 通常 void ;返回通过 buffer 或 side channel,非
RetCC寄存器。 SIFrameLowering::determineCalleeSaves:若isEntryFunction()则 不 做常规 VGPR CSR save(早退)。
Part C --- Graphics 与其它 CC
| CC | 用途 | 备注 |
|---|---|---|
AMDGPU_PS |
Pixel shader | processPSInputArgs、插值模式 workaround |
AMDGPU_VS/GS/HS/ES/LS/CS |
图形管线 | isGraphics();HSA OS 下 compute-only 限制 |
AMDGPU_Gfx |
Gfx 统一 | CC_SI_Gfx / CSR_AMDGPU_SI_Gfx |
AMDGPU_CS_Chain |
Mesh 链式 | getCallPreservedMask → AMDGPU_AllVGPRs_RegMask(假定不返回) |
本文档集 不展开 图形管线全部输入语义;详见 SIISelLowering::LowerFormalArguments 中 IsGraphics 分支。
7. 编译流水线与分工
text
Clang AMDGPUABIInfo::computeInfo
↓ AMDGPU_KERNEL → classifyKernelArgumentType
↓ else → classifyArgumentType (16-reg limit)
[LLVM IR]
↓ AMDGPUPromoteKernelArguments / PreloadKernelArguments 等
[ISel LowerFormalArguments]
├─ Kernel → analyzeFormalArgumentsCompute + User SGPR
└─ Device → CCInfo.AnalyzeFormalArguments(CC_AMDGPU_Func)
[LowerCall + getCallPreservedMask]
[Regalloc --- RegMask / AllocationOrder CSR 队尾]
[PEI --- determineCalleeSaves (VGPR) + determineCalleeSavesSGPR]
[SILowerSGPRSpills --- SGPR spill 路径]
| 问题 | 机制 | 文档 |
|---|---|---|
| Caller 跨 call 保留 VGPR | RegMask + Greedy | <RegMask-AMDGPU.md> |
| Callee 改写 CSR VGPR | PEI + scratch spill | <PEI-AMDGPU.md> |
| SGPR save | determineCalleeSavesSGPR / SILowerSGPRSpills |
<PEI-AMDGPU.md> |
| 分配顺序 | RegisterClassInfo + CSR 掩码 |
<AllocationOrder-AMDGPU.md> |
8. 调试与源文件
8.1 调试
| 目的 | 方法 |
|---|---|
| Kernel CC | F.getCallingConv() == 91 |
| Kernarg 偏移 | -debug ISel;analyzeFormalArgumentsCompute |
| User SGPR 分配 | SIMachineFunctionInfo;MIR 早期 live-in |
| Call RegMask | MIR regmask;SIISelLowering::LowerCall |
| PEI CSR | -print-after=prologepilog |
| Code object | llvm-objdump --amdhsa / readobj |