LLVM TargetInstrInfo VS MachineInstr

LLVM TargetInstrInfo VS MachineInstr,第1张

TargetInstrInfo

TargetInstrInfo类提供的机器指令描述接口,由于机器指令通常是与target 相关,因此该类提供的大部分接口都是虚函数,具体实现有每个target 后端来实现,

其中TargetInstrInfo类接口主要提供获取机器指令信息接口,出了一些标准接口之外,每个target在实现的机器指令接口类还可以可以按照需要进行扩展,

整个amdgpu后端机器接口指令继承关系如下图所示:

 MCInstrInfo

MCInstrInfo该类为描述机器指令接口基础类,位于llvm\include\llvm\MC\MCInstrInfo.h文件中,提供了几个基本的指令接口,该接口是所有指令描述共有的属性接口:

Interface

description

unsigned getNumOpcodes()用于获取指令的op 数目
MCInstrDesc &get(unsigned Opcode)返回对机器指令描述
StringRef getName(unsigned Opcode)根据opcode 返回指令的名称
bool getDeprecatedInfo(MCInst &MI, const           MCSubtargetInfo &STI,std::string &Info)该指令是否被废弃掉,返回值true表明指令被废弃

TargetInstrInfo

TargetInstrInfo:针对所有target 机器指令描述具有相同属性抽象:

位于llvm\lib\CodeGen\TargetInstrInfo.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 后端提供的机器指令描述接口类,位于\llvm\lib\Target\AMDGPU\SIInstrInfo.cpp文件中,

该接口提供了指令中的大部分接口,一般需要查询指令信息或者对一个指令进行 *** 作可以使用该类接口:

  • isXXX接口:主要查询指令的指令是否属于某些类型
  • insertXXX接口:提供在指令前插入指令类型指令,例如插入s_noop指令接口insertNoop, 插入一个返回指令insertReturn
  • getXXX接口:获取指令指令中信息。

SIInstrInfo主要提供机器指令接口,接口参数中一般需要传入所需要 *** 作MachineInstr 机器指令

每个target会有全局唯一SIInstrInfo接口

GCNSubtarget

该类提供了对target进行抽象封装,里面包含对target特性记录以及重要数据:主要分为数据部分和接口部分,

位于llvm\lib\Target\AMDGPU\GCNSubtarget.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 无关,位于llvm\include\llvm\MC\MCSubtargetInfo.h文件
  • TargetSubtargetInfo:大部分都是虚拟接口,由target实现,位于llvm\include\llvm\CodeGen\TargetSubtargetInfo.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 机器指令,机器指令以三地址表示形式

该类位于llvm\lib\CodeGen\MachineInstr.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机制,用来创建一个机器指令,位于llvm\include\llvm\CodeGen\MachineInstrBuilder.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类来实现构建一个机器指令:

 MachineInstrBuilder

MachineInstrBuilder类除了提供创建MachineInstr之外,还提供了创建之后各种 *** 作:LLVM: llvm::MachineInstrBuilder Class Reference

例如下图:

 参考资料

The LLVM Target-Independent Code Generator — LLVM 15.0.0git documentation

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1352559.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-14
下一篇 2022-06-14

发表评论

登录后才能评论

评论列表(0条)

保存