当前位置:主页 > 查看内容

一文看懂RISC-V代码密度

发布时间:2021-05-07 00:00| 位朋友查看

简介:代码密度的决定因素 如上面的倒金字塔所示 代码密度主要由指令集、ABI、编译器、Runtime库、程序代码五个部分决定。处在金字塔的越底端 说明该因素的越底层 更新的频率越小 但辐射和影响的范围却越广。 指令集 指令集是代码密度最根本的决定性因素 它决定了……
代码密度的决定因素

image

如上面的倒金字塔所示 代码密度主要由指令集、ABI、编译器、Runtime库、程序代码五个部分决定。处在金字塔的越底端 说明该因素的越底层 更新的频率越小 但辐射和影响的范围却越广。

指令集

指令集是代码密度最根本的决定性因素 它决定了一个操作在最优的情况下需要编译成多少位宽的编码。

很多体系结构比如ARM、RISC-V、C-SKY都是16位指令、32位指令混编的 同样的一条指令 如果能够被编译成16位指令 那么它显然比编译成32位指令占用更小的空间 再比如 一个乘累加的操作 如果指令集中存在乘累加指令 那么它只需要一条指令来实现乘累加操作 如果没有则需要至少两条指令来完成相同的操作 假设指令都是32位的 显然一条指令将占用更少的空间。

由于指令集的编码空间是有限的 所以指令集设计的核心是将哪些指令 包括指令操作数的范围 放到编码空间当中 就像一个商场的店面是有限的 当我们把需求最广的商家引进来时 商场的销量就会达到最高。

ABI

ABI的全称是Application Binary Interface 是二进制级别的协议 它指导着编译器如何生成代码和二进制程序 同样也指导着用户如何写汇编代码。它主要包含函数调用约定 calling convention 、数据的对齐方式等内容。

其中对代码密度影响最大的就是函数调用约定 它规定了堆栈寄存器、链接寄存器、哪些寄存器寄存器需要在函数头尾保存和恢复、哪些寄存器可以作为参数寄存器等 还有一些特殊用途的寄存器。大部分特殊寄存器都是会被高频使用的 配合指令集设计可以降低代码密度 需要保存和恢复的寄存器个数同样也会影响代码密度。

编译器

编译器是开发者最直接接触的工具 也是给开发者体感最强的代码密度影响因素。它对代码密度的影响主要体现在两方面

编译器本身的优化能力 优化能力的强弱是影响编译器产品竞争力的最主要的因素。编译器的使用方法 比如GCC 除了添加-Os之外 还可以添加-ffunction-sections -fdata-sections -Wl,--gc-sections来删除没有用到的函数。Runtime库

Runtime库是指程序运行所需的一些基本的函数库 它们一般都是预先编译好 和编译器一起打包发布 是工具链的一部分。由于这些函数的使用频率较高 一般程序都会用到一部分Runtime库的函数 对这些函数做针对性地优化会有比较好的收益。

程序代码

开发者书写的代码质量也会影响程序的代码密度 虽然编译器能够优化一部分冗余代码 但是并不能保证百分之百的优化 所以开发者也要注意代码的质量

RISC-V架构的代码密度现状

RISC-V的代码密度表现一直被人诟病 那么 它的现状真的这么不值一提吗

首先 RISC-V对代码密度做过一些专门的优化。在指令集方面 它通过量化分析的方法测试了spec等benchmark 找到高频指令并将它们放到16位指令的编码当中 这就是目前的compress指令集 在ABI方面 rv32e通过限制16个寄存器 使代码可以生产更多的16位指令 在编译器和Runtime中 它支持-msave-restore功能通过库函数调用的方式弥补了由于没有push/pop指令造成的一部分代码密度损失。这里需要特别指出的是 RISC-V的链接器做了较多的relax优化 即某些指令的目标符号距离比较接近的时候 可以优化使用更少的指令。比如函数跳转 比如具体在4k之内 可以使用一条jalr指令实现 而如果超过4k的话 则需要auipc jalr或者lui jalr两条指令实现。一般在未链接的object文件中 预留的都是指令条数最多的形式 链接之后很大一部分将被优化。如果测试的benchmark如果统计的是object文件 比如CSiBE 那么结果会比实际的要差一些。

那么 在做了这些优化之后 为什么RISC-V的代码密度还是被这么多人诟病呢 主要是由于compress指令集设计时 基于的benchmark是spec2006 它在应用PC端非常具有代表性 但在嵌入式领域却不具有典型性。所以在RISC-V 64位核中 它的代码密度表现还不错 但是在真正关心代码密度的嵌入式领域表现却不尽如人意。其次 ABI也需要重新针对嵌入式领域做量化评估和设计。

平头哥对RISC-V的代码密度优化

针对代码密度 RISC-V社区目前也在不断地优化中 比如code-size TG和EABI TG的成立。平头哥也参与其中 在优化代码密度的道路上不断前行。目前 平头哥所做的优化有如下两个方面

Runtime库

平头哥设计开发了一套针对嵌入式领域的、最大化优化代码密度的Lower-Level Runtime Library。目前玄铁E902、玄铁E906和玄铁E907均已支持该Runtime库 它相对于libgcc提升40% 相对于Arm的macrolib 玄铁E902与M0-plus相当 玄铁E906、玄铁E907与M4相当。

ABI

目前 社区正在设计、制定针对嵌入式领域的新的ABI——EABI Embedded ABI 它不仅会调整Calling Convention以减少中断延迟 也会考虑代码密度 使用量化分析地方法设计出一套对嵌入式领域优化的ABI。平头哥作为EABI Task Group的Co-Chair 也参与其中推动EABI的前进。

作为平头哥玄铁系列科普文章之一 以上是本文关于RISC-V代码密度的介绍及平头哥在其中的优化成果的简介 更多关于RISC-V指令集优劣势分析等内容可参见后续文章。


本文转自网络,原文链接:https://developer.aliyun.com/article/783932
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文

  • 周排行
  • 月排行
  • 总排行

随机推荐