TargetInstrInfo
TargetInstrInfo类提供的机器指令描述接口,由于机器指令通常是与target 相关,因此该类提供的大部分接口都是虚函数,具体实现有每个target 后端来实现,
其中TargetInstrInfo类接口主要提供获取机器指令信息接口,出了一些标准接口之外,每个target在实现的机器指令接口类还可以可以按照需要进行扩展,
整个amdgpu后端机器接口指令继承关系如下图所示:
MCInstrInfoMCInstrInfo该类为描述机器指令接口基础类,位于llvmincludellvmMCMCInstrInfo.h文件中,提供了几个基本的指令接口,该接口是所有指令描述共有的属性接口:
| Interface | description |
|---|---|
| unsigned getNumOpcodes() | 返回机器指令集中的opcodes数目,可以理解为target所支持的指令集数目 |
| MCInstrDesc &get(unsigned Opcode) | 返回对机器指令描述 |
| StringRef getName(unsigned Opcode) | 根据opcode 返回指令的名称 |
| bool getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI,std::string &Info) | 该指令是否被废弃掉,返回值true表明指令被废弃 |
TargetInstrInfo
TargetInstrInfo:针对所有target 机器指令描述具有相同属性抽象:
位于llvmlibCodeGenTargetInstrInfo.cpp文件中
- 该类中的接口很多都是虚拟接口,主要是因为每个target指令不同,因此需要针对target,在继承TargetInstrInfo基础上对该虚拟接口进行实现,
- 该类在MCInstrInfo类基础上进一步扩展出了新的接口,对机器指令的常用操作进一步做了抽象。
- 该类提供的接口大部分都需要提供MachineInstr即通过指令选择调度生成的机器三地址形式
- 该类接口使用都是位于指令选择调度之后。
AMDGPUGenInstrInfo
AMDGPUGenInstrInfo类为AMDGPU 后端对TargetInstrInfo继承,
该类位于build/lib/Target/AMDGPU/AMDGPUGenInstrInfo.inc,是由TableGen自动生成,生成命令如下:
llvm-tblgen -gen-instr-info ./AMDGPU.td -I ../../../include
该类在AMDGPU中也属于一个过渡类,本身并没有任何多余功能:
namespace llvm {
struct AMDGPUGenInstrInfo : public TargetInstrInfo {
explicit AMDGPUGenInstrInfo(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);
~AMDGPUGenInstrInfo() override = default;
};
} // end namespace llvm
SIInstrInfo
SIInstrInfo为AMDGPU 后端提供的机器指令描述接口类,位于llvmlibTargetAMDGPUSIInstrInfo.cpp文件中,
该接口提供了指令中的大部分接口,一般需要查询指令信息或者对一个指令进行操作可以使用该类接口:
- isXXX接口:主要查询指令的指令是否属于某些类型
- insertXXX接口:提供在指令前插入指令类型指令,例如插入s_noop指令接口insertNoop, 插入一个返回指令insertReturn
- getXXX接口:获取指令指令中信息。
SIInstrInfo主要提供机器指令接口,接口参数中一般需要传入所需要操作MachineInstr 机器指令
每个target会有全局唯一SIInstrInfo接口
GCNSubtarget
该类提供了对target进行抽象封装,里面包含对target特性记录以及重要数据:主要分为数据部分和接口部分,
位于llvmlibTargetAMDGPUGCNSubtarget.cpp
数据记部分主要记录当前target一些特性:
... ... // for XNACK. bool EnableXNACK; bool EnableTgSplit; bool EnableCuMode; bool TrapHandler; ... ... // Subtarget statically properties set by tablegen bool FP64; bool FMA; bool MIMG_R128; bool CIInsts; bool GFX8Insts; bool GFX9Insts; bool GFX90AInsts; bool GFX10Insts; bool GFX10_3Insts; bool GFX7GFX8GFX9Insts; bool SGPRInitBug; bool NegativeScratchOffsetBug; bool NegativeUnalignedScratchOffsetBug; bool HasSMemRealTime; bool HasIntClamp; bool HasFmaMixInsts; bool HasMovrel; bool HasVGPRIndexMode; bool HasScalarStores; bool HasScalarAtomics; bool HasSDWAOmod; bool HasSDWAScalar; bool HasSDWASdst; bool HasSDWAMac; bool HasSDWAOutModsVOPC; ... ..
接口部分主要分为:
- getXXXX接口:主要用于提供获取target中相关特性信息
- hasXXX接口:主要查询是否用于某些特性,例如:hasAddr64、hasAddr64等
SIInstrInfo位置
SIInstrInfo属于指令集描述接口,本身也属于GCNSubtarget中一员:
GCNSubtarget 提供了getInstrInfo()用于方便获取SIInstrInfo
GCNSubtarget类继承关系GCNSubtarget整个类继承关系如下图所示:
继承关系思路与类似:
- MCSubtargetInfo 为所有subtarget的基础抽象,该抽象与具体target 无关,位于llvmincludellvmMCMCSubtargetInfo.h文件
- TargetSubtargetInfo:大部分都是虚拟接口,由target实现,位于llvmincludellvmCodeGenTargetSubtargetInfo.h文件
- AMDGPUGenSubtargetInfo: 由tabelGen 生成的AMDGPUGenSubtargetInfo.inc文件中,生成命令为:
llvm-tblgen -gen-subtarget ./AMDGPU.td -I ../../../includ
- AMDGPUSubtarget:为AMDGPU 基础类,里面包括AMGPU各种基础特性以及接口实现,作为GCN和R600两个平台中具有的相同特性实现
- GCNSubtarget: 为GCN subtarget实现。
MachineInstr
MachineInstr 又简称为MI,LLVM通过指令选择及调度将IR中的IR指令转换成对应的target 机器指令,机器指令以三地址表示形式
该类位于llvmlibCodeGenMachineInstr.cpp
每个MachineInstr 实例代表了一条机器指令
MachineInstr是对机器指令的抽象,只能用来跟踪指令的operands以及opcode。
MachineInst类中没有任何关系指令的描述及解释信息,如果要获取指令中描述信息以及其他操作需要通过TargetInstrInfo中提供的接口实现。
operands可能为:register、 a constant integer,a basic block reference, etc
opcode :对应的是机器指令opcode, 一般位于 *InstrInfo.td, AMDGPU对应的opcode 会在编译之后位于build/lib/Target/AMDGPU/AMDGPUGenInstrInfo.inc文件中,手动生成命令如下:
llvm-tblgen -gen-instr-info ./AMDGPU.td -I ../../../include/
调试过程中可以使用上述命令生成AMDGPUGenInstrInfo.inc文件查看AMDGPU指令对应opcode.
如何创建MachineInstr
LLVM提供了BuildMI机制,用来创建一个机器指令,位于llvmincludellvmCodeGenMachineInstrBuilder.h文件
例如在SIInstrInfo中提供了insertNoops方法 用来创建一个s_nop指令并查到到该指令之前:
void SIInstrInfo::insertNoops(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned Quantity) const {
DebugLoc DL = MBB.findDebugLoc(MI);
while (Quantity > 0) {
unsigned Arg = std::min(Quantity, 8u);
Quantity -= Arg;
BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
}
}
BuildMI最终是通过MachineInstrBuilder类来实现构建一个机器指令:
MachineInstrBuilderMachineInstrBuilder类除了提供创建MachineInstr之外,还提供了创建之后各种操作:LLVM: llvm::MachineInstrBuilder Class Reference
例如下图:
参考资料The LLVM Target-Independent Code Generator — LLVM 15.0.0git documentation



