AMDGPU 后端 ABI 总览

AMDGPU 后端 ABI 总览

适用范围llvm/lib/Target/AMDGPU(GCN/SI 及以后,GCNSubtarget
CPU ABI 参考(可选)llvm/lib/Target/X86/X86CallingConv.td(如 CC_X86_64_C

目录

  1. [什么是后端 ABI](#什么是后端 ABI)
  2. [ABI 七个维度](#ABI 七个维度)
  3. [多套并行 ABI](#多套并行 ABI)
  4. [Part A --- Device/Leaf 可调用 ABI](#Part A — Device/Leaf 可调用 ABI)
  5. [Part B --- Kernel(Compute)入口 ABI](#Part B — Kernel(Compute)入口 ABI)
  6. [Part C --- Graphics 与其它 CC](#Part C — Graphics 与其它 CC)
  7. 编译流水线与分工
  8. 调试与源文件

1. 什么是后端 ABI

ABI 规定二进制层面函数如何传参、返回、保存寄存器、使用栈/scratch,以及 kernel 如何与 runtime(ROCm/HSA/PAL)对接。

AMDGPU 后端实现分散在:

组件 路径
TableGen CC/CSR AMDGPUCallingConv.td
寄存器与 RegMask SIRegisterInfo.cpp
ISel 传参 SIISelLowering.cppAMDGPUISelLowering.cpp
栈帧 / PEI SIFrameLowering.cppSILowerSGPRSpills.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/ColdAMDGPU_GfxAMDGPU_PS/VS/...AMDGPU_CS_Chain
3 参数/返回 Leaf:CC_AMDGPU_Func;SI shader:CC_SI_SHADER;Kernel:analyzeFormalArgumentsComputeMem/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 / ColdCC_AMDGPU_Func HIP device 函数、内部 leaf VGPR0-31 / SGPR0-29inreg)+ 栈 VGPR0-31
SI Shader(非 SI 以前) CC_AMDGPUCC_SI_SHADER 部分 legacy 路径 SGPR0-43 / VGPR0-135 RetCC_SI_Shader
AMDGPU_Gfx AMDGPU_Gfx Gfx pipeline CC_SI_GfxSGPR4-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-29inreg)+ 栈/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 互调多走 CCC_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 / getCallPreservedMaskSIRegisterInfo.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::CustomMemInIndexBasePartOffsetMemVT)。
  • 使用 CC_AMDGPU_Func 的寄存器分配表。

B.3 LowerFormalArguments(Kernel 分支)

SIISelLowering.cpp

  1. IsKernelanalyzeFormalArgumentsCompute(CCInfo, Ins)
  2. allocateSpecialEntryInputVGPRs / allocateHSAUserSGPRs(workgroup ID、dispatch ptr、kernarg segment ptr 等)
  3. 可选 allocatePreloadKernArgSGPRshasKernargPreload
  4. 从 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 等

详见 allocateHSAUserSGPRsSIMachineFunctionInfo

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 链式 getCallPreservedMaskAMDGPU_AllVGPRs_RegMask(假定不返回)

本文档集 不展开 图形管线全部输入语义;详见 SIISelLowering::LowerFormalArgumentsIsGraphics 分支。


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 regmaskSIISelLowering::LowerCall
PEI CSR -print-after=prologepilog
Code object llvm-objdump --amdhsa / readobj
相关推荐
lbaihao5 天前
LLVM Cpu0 调用规则解析
开发语言·前端·python·llvm
林多7 天前
【Android】 GPU过度绘制实现原理
android·gpu·性能·实现原理·过度绘制·overdraw
lbaihao8 天前
LLVM Cpu 后端中具体的指令定义和模式匹配规则
llvm
lbaihao8 天前
LLVM 后端中 Cpu 目标机器的 SelectionDAG 节点定义
llvm
数据与后端架构提升之路10 天前
深度学习性能调优全景指南:数据、计算、显存、通信四大瓶颈的破局之道
深度学习·gpu·性能调优
Eloudy12 天前
华为UB协议与NVIDIA NVLink/NVSwitch在PCIe GPU场景下的技术替代性分析
gpu
weixin_4217252614 天前
C语言已逐渐落伍 什么样的语言能取代C语言?
c语言·编程语言·llvm·替代方案·go和rust
木雷坞15 天前
内网模型服务启动链路分层实践
docker·容器·gpu
十五年专注C++开发16 天前
浅谈LLVM
开发语言·c++·qt·clang·llvm