LLVM编译器后端比较功能的添加

news2024/9/30 1:25:47

1.动机

从机器层面上来看,控制流类的跳转指令分为无条件跳转和有条件跳转,无条件跳转 JMP,有条件跳转 JEQ、JNE、JLT、JGT、JLE、JGE,这部分指令是需要通过检查 condition code (SW 寄存器)来决定跳转条件;J 类型指令依赖的 condition code 是通过比较指令(比如 CMP)的结果来设置的。如下图所示,JNE跳转指令通过检查SW寄存器的状态以决定是否发生跳转。因此,为了支持控制流功能,首先要打通比较功能。

e21b97084ddb77003b37c90b29701367.png


2.LLVM IR 中的比较指令

LLVM IR提供的 int 类型比较指令为 icmp。其接受三个参数:比较方案以及两个比较参数。

%result = icmp ule i32 %a, %b

ule是比较方案,其中 u 为 unsigned int,le 为 lower than or equal,%a和%b就是用来比较的两个数,而icmp则返回一个i1类型的值,用来表示结果是否为真。

与ule类似的比较方案有多种,如:

  • 等于与不等于:eq、ne;

  • 无符号比较:ugt、uge、ult、ule, 分别对应无符号的大于、大于等于、小于、小于等于;

  • 有符号比较:sgt、sge、slt、sle, 分别对应有符号的大于、大于等于、小于、小于等于。

3.实现比较功能的添加

3.1 定义format

class FA<bits<8> op, dag outs, dag ins, string asmStr,
         list<dag> pattern, InstrItinClass itin>
  : Cpu0Inst<outs, ins, asmStr, pattern, itin, FrmA>
{
  bits<4>  ra;
  bits<4>  rb;
  bits<4>  rc;
  bits<12> shamt;

  let Opcode = op;

  let Inst{23-20} = ra;
  let Inst{19-16} = rb;
  let Inst{15-12} = rc;
  let Inst{11-0}  = shamt;
}

rbrc为两个寄存器类型源操作数,用于存放比较的数据,ra为寄存器类型目的操作数,用来存放比较的结果。

class FL<bits<8> op, dag outs, dag ins, string asmStr,
         list<dag> pattern, InstrItinClass itin>
  : Cpu0Inst<outs, ins, asmStr, pattern, itin, FrmL>
{
  bits<4>  ra;
  bits<4>  rb;
  bits<16> imm16;

  let Opcode = op;

  let Inst{23-20} = ra;
  let Inst{19-16} = rb;
  let Inst{15-0}  = imm16;
}

rb为寄存器类型源操作数,用于存放比较的数据,imm16是用于比较的16位立即数,ra为寄存器类型目的操作数,用来存放比较的结果。

3.2 定义指令

class SetCC_R<bits<8> op, string instrAsm, PatFrag condOp,
              RegisterClass RC>
  : FA<op, (outs GPROut:$ra), (ins RC:$rb, RC:$rc),
       !strconcat(instrAsm, "\t$ra, $rb, $rc"),
       [(set GPROut:$ra, (condOp RC:$rb, RC:$rc))],
       IIAlu>, Requires<[HasSlt]> {
  let shamt = 0;
}
def SLT      : SetCC_R<0x28, "slt", setlt, CPURegs>;
def SLTu     : SetCC_R<0x29, "sltu", setult, CPURegs>;

SetCC_R继承自上面定义的FASLTSLTu对应着小于、无符号小于两种比较方案

class SetCC_I<bits<8> op, string instrAsm, PatFrag condOp, Operand Od,
              PatLeaf immType, RegisterClass RC>
  : FL<op, (outs GPROut:$ra), (ins RC:$rb, Od:$imm16),
       !strconcat(instrAsm, "\t$ra, $rb, $imm16"),
       [(set GPROut:$ra, (condOp RC:$rb, immType:$imm16))],
       IIAlu>, Requires<[HasSlt]>;

class FMem<bits<8> op, dag outs, dag ins, string asmStr, list<dag> pattern,
           InstrItinClass itin>
  : FL<op, outs, ins, asmStr, pattern, itin> {
  bits<20> addr;
  let Inst{19-16}   = addr{19-16};
  let Inst{15-0}    = addr{15-0};
  let DecoderMethod = "DecodeMem";
}
def SLTi     : SetCC_I<0x26, "slti", setlt, simm16, immSExt16, CPURegs>;
def SLTiu    : SetCC_I<0x27, "sltiu", setult, simm16, immSExt16, CPURegs>;

SetCC_I继承自上面定义的FLSLTiSLTiu对应着立即数小于、立即数无符号小于两种比较方案。

3.3 定义Pattern

上述四条指令只提到了小于、无符号小于两种比较方案,另外的比较方案没有定义。针对这种指令集中没有定义的比较方案需要借助Pattern定义。

指令选择过程就是DAG的模式匹配过程,模式的定义其主要在td文件中进行描述。当一个匹配找到后,将其DAG中的Node替换为具体的机器指令或伪指令。所以td文件中的Pattern的定义对于指令选择起到至关重要的作用。

每一个Pattern记录继承自 Pat class,其有两个参数,第一个参数DAG图中待匹配的模式,第二个参数是一个由机器指令组成DAG,当一个 Pattern 匹配后,将使用第二个参数替换第一个参数。以大于和大于等于为例,比较方案的模式定义如下:

  • 大于(setgt、setugt)

multiclass SetgtPatsSlt<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
  def : Pat<(setgt RC:$lhs, RC:$rhs),
  // a > b is equal to b < a is equal to setlt(b, a)
            (SLTOp RC:$rhs, RC:$lhs)>;
  def : Pat<(setugt RC:$lhs, RC:$rhs),
            (SLTuOp RC:$rhs, RC:$lhs)>;
}

defm : SetgtPatsSlt<CPURegs, SLT, SLTu>;
  • 大于等于(setge、setuge)

multiclass SetgePatsSlt<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> {
  def : Pat<(setge RC:$lhs, RC:$rhs),
  // a >= b is equal to b <= a
            (XORi (SLTOp RC:$lhs, RC:$rhs), 1)>;
  def : Pat<(setuge RC:$lhs, RC:$rhs),
            (XORi (SLTuOp RC:$lhs, RC:$rhs), 1)>;
}

defm : SetgePatsSlt<CPURegs, SLT, SLTu>;

4.测试 (以大于为例)

  • 测试用例

int test_setxx()
{
  int a = 5;
  int b = 3;
  int c;

  c = (a > b);   // sgt, c = 1

  return (c);
}
  • LLVM IR

%a = alloca i32, align 4
  %b = alloca i32, align 4
  %c = alloca i32, align 4
  store i32 5, i32* %a, align 4
  store i32 3, i32* %b, align 4
  %0 = load i32, i32* %a, align 4
  %1 = load i32, i32* %b, align 4
  %cmp = icmp sgt i32 %0, %1
  %conv = zext i1 %cmp to i32
  store i32 %conv, i32* %c, align 4
  %2 = load i32, i32* %c, align 4
  ret i32 %2
}
  • 指令选择前后的DAG

041d51d97620a0e8683a70c055a40eee.png

5d1c094ca695c3bde4eb71dd6ba71bb8.png


  • 汇编

test_setxx:
 .frame $fp,16,$lr
 .mask  0x00000000,0
 .set noreorder
 .set nomacro
# %bb.0:                                # %entry
 addiu $sp, $sp, -16
 addiu $2, $zero, 5
 st $2, 12($sp)
 addiu $2, $zero, 3
 st $2, 8($sp)
 ld $2, 12($sp)
 ld $3, 8($sp)
 cmp $sw, $3, $2
 andi $2, $sw, 1
 st $2, 4($sp)
 ld $2, 4($sp)
 addiu $sp, $sp, 16
 ret $lr
 nop
 .set macro
 .set reorder
 .end test_setxx
$func_end0:
 .size test_setxx, ($func_end0)-test_setxx
                                        # -- End function

5.总结

LLVM编译器后端的主要工作是将LLVM中间端表达式(IR)转换成汇编文件,Cpu0 是一个非常简单的 RISC 架构处理器,本文以Cpu0作为硬件的例子,来构建能适配它的编译器后端,主要讲述了比较指令在整个控制流当中的作用并梳理了在LLVM后端中添加比较功能的过程。在编译器后端的开发过程中有一定的参考作用。可能存在认知上的偏差,也请大佬多多指教,笔者也会在学习中一步步改正错误,欢迎交流技术心得。

c537289a22c4d76a1fca60a12a9615e7.png


参考文献

  • https://llvm.org/docs/WritingAnLLVMBackend.html

  • https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl05.html

  • https://zhuanlan.zhihu.com/p/386457923

  • https://zhuanlan.zhihu.com/p/163328574

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/438167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解析基于Pytorch的残差神经网络(ResNet18模型),并使用数据集CIFAR10来进行预测与训练

解析基于Pytorch的残差神经网络&#xff08;ResNet18模型&#xff09;&#xff0c;并使用数据集CIFAR10来进行预测与训练 1.0、什么是残差神经网络 注&#xff1a;本人才疏学浅&#xff0c;如有纰漏&#xff0c;请不吝赐教 残差神经网络其实是与卷积神经网络分不开的&#x…

Java项目无法启动排查

Java项目无法启动排查 1.启动服务发现 无法写入日志也无法启动项目2.df查看磁盘占用情况 、free -h查看内存占用、top查看CPU使用率负载率3.此时磁盘满4.清理磁盘5.定时任务 1.启动服务发现 无法写入日志也无法启动项目 2.df查看磁盘占用情况 、free -h查看内存占用、top查看C…

计及源荷不确定性的综合能源生产单元运行调度与容量配置优化研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

java贸易企业工作信息管理与利润返现系统sxA5进销存程序

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1 课题背景 1 1.2 研究现状 1 本章小结 1 第2章 可行性分析 2 2.1 经济可行性 2 2.2 技术可行性 2 2.3 操作可行性 2 2.4 业务流程分析 3 本章小结 3 第3章 需求分析 4 3.1 需求分析 4 …

数据库基础篇 《3. 基本的SELECT语句》

目录 1. SQL概述 1.1 SQL背景知识 1.2 SQL语言排行榜 1.3 SQL 分类 2. SQL语言的规则与规范 2.1 基本规则 2.2 SQL大小写规范 &#xff08;建议遵守&#xff09; 2.3 注释 2.4 命名规则&#xff08;暂时了解&#xff09; 2.5 数据导入指令 3. 基本的SELECT语句 3.0…

【攻城狮计划】Renesas RA2E1 运行 命名

&#x1f6a9;WRITE IN FRONT&#x1f6a9; &#x1f50e;介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四"&#x1f50e;&#x1f3c5;荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星TOP10…

法大大合同批量下载

1.测试需求 法大大网上80万合同需要下载下来 其实总共1392392页,20885871万条合同数据要下载下来的 2.测试需求分析与验证 2.1调通接口,取到合同列表页信息 遇到的问题: 登录页面有图形验证码,不好处理 解决: 手动登录后用已经有的cookie,如果超时需要重新登录抓取co…

ChatGPT闲谈——火出圈的为什么是 OpenAI?

ChatGPT 走入大众视野之后&#xff0c;AIGC 行业迎来了爆发&#xff0c;尤其是上个月&#xff0c;仿佛每一天都可能是「历史性」的一天。 现在各大网站已经有非常多的优秀创作者进行总结和分析&#xff0c;都是值得一阅的好文。今天本文也分享了关于ChatGPT的看法&#xff0c;有…

顺序表—C语言实现数据结构

本期带大家一起来用C语言代码实现顺序表&#x1f308;&#x1f308;&#x1f308; 文章目录 一、顺序表的概念✅二、顺序表的结构✅三、顺序表的实现&#xff08;动态顺序表&#xff09;✅一、&#x1f536;定义顺序表结构体&#x1f536;二、&#x1f536;接口的实现&#x1…

【原理图专题】案例:从集成的电平转换芯片换成三极管分立电平转换怎么就报异常

本案例是一个已经小批量量产的设备,不是我测试出来的,但是也算是我之前一手造成的,因为原理图这部分是我修改的。 异常发现最近生产的整机有部分非接读卡时无法控制到蜂鸣器发声音。我们的设计是这样的,有两个MCU互相通信,一个MCU是控制蜂鸣器的,另一个MCU通过SPI与非接芯…

UEFI Driver Services

为UEFI驱动程序提供的UEFI引导服务和UEFI运行时服务一般可分为三个方面&#xff1a; 驱动通常使用很少使用的服务不应该使用的服务 UEFI驱动程序通常使用的服务 下表列出了UEFI驱动程序通常使用的UEFI服务。接下来&#xff0c;讨论将简要描述每种服务&#xff0c;它们为什么…

scala函数参数

目录 可变参数如果参数列表在存在多个参数&#xff0c;那么可变参数一般放置在最后参数默认值&#xff0c;一般将有默认值的参数放置在参数列表的后面带名参数&#xff08;一般不使用&#xff0c;除多个参数有默认值且只需给极少个参数赋值的情况&#xff09; 可变参数 当有不…

无线测温在线监测系统工作原理与产品选型

摘要&#xff1a;本文首先介绍了无线测温在线监测系统的基本工作原理以及软硬件组成&#xff0c;重点介绍了在线监测的无线测温技术特点。在此研究基础上&#xff0c;探讨了无线测温在线监测系统在实际工作场景中的应用案例&#xff0c;证明了其在温度检测方面的重要应用价值。…

浅谈数字化工厂五大核心系统

一、什么是数字化工厂 数字化工厂是将数字技术应用于工厂生产、管理和运营中的一种方式&#xff0c;可以帮助企业提高生产效率和质量&#xff0c;降低成本和风险&#xff0c;提高竞争力和市场份额。数字化工厂是中小制造业企业自主建设制造业信息化的途径。 简道云数字化工厂解…

stm32虚拟串口无法连接,驱动安装,DFU驱动安装

虚拟usb串口设备 插上设备后, COM这里多了一个端口, 但是其用串口调试助手无法打开 在其他设备这里多了一个STM32xx Virtual COM, 更新驱动程序 浏览我的电脑以查找驱动程序让我从计算机上的可用驱动列表中选取端口(COM和LPT)厂商: STMicroelectronics 型号: STMicroelectroni…

倾斜摄影三维模型、激光点云、正射影像、数字高程模型如何实现在线浏览?

四维轻云是成都远石技术团队基于浏览器打造的一款地理空间数据管理云平台&#xff0c;可实现TB级大规模倾斜摄影三维模型发布管理&#xff0c;并支持私有化部署和高阶功能定制化开发。 1、注册登录 首先在四维轻云官网点击「立即试用」按钮&#xff0c;进入登录页面并点击「注…

手写vue(三)模板渲染解析

一、目标 创建一个Vue实例时&#xff0c;我们可以传入el配置项&#xff0c;去指定一个DOM元素作为Vue容器&#xff0c;而这个Vue容器中&#xff0c;可以使用例如插值表达式等Vue框架提供的语法&#xff0c;并且能够渲染到浏览器页面上。 而浏览器并不能解析这些Vue语法&#xf…

Ubuntu20.04软件安装大全

目录 Ubuntu20.04 软件安装大全前言1. Windows和Ubuntu双系统安装1.1 下载Ubuntu系统镜像1.2 磁盘分区1.3 GPT分区安装Ubuntu1.4 系统完成后的一些设置1.5 遇到的一些小bug 2. 换源2.1 apt换源2.2 pip换源 3. 显卡驱动安装3.1 卸载显卡驱动3.2 准备工作3.3 驱动安装3.4 验证 4.…

分享5款小软件,让你打造更舒适的办公电脑

每次发现实用的小工具,都会有种小小的成就感&#xff0c;这也是我喜欢收集和分享高效工具的原因。 图标定制软件——CustomizerGod CustomizerGod是一款强大的电脑图标定制软件&#xff0c;可以让你随心所欲地改变系统中的任何图标。你可以使用CustomizerGod来修改桌面、任务…

Node 01-Buffer

Buffer&#xff08;缓冲器&#xff09; 概念 Buffer 是一个类似于数组的 对象 &#xff0c;用于表示固定长度的字节序列 Buffer 本质是一段内存空间&#xff0c;专门用来处理 二进制数据 。 特点 Buffer 大小固定且无法调整Buffer 性能较好&#xff0c;可以直接对计算机内存…