CN114816532A - 一种提高risc-v二进制代码密度的寄存器分配方法 - Google Patents
一种提高risc-v二进制代码密度的寄存器分配方法 Download PDFInfo
- Publication number
- CN114816532A CN114816532A CN202210419942.8A CN202210419942A CN114816532A CN 114816532 A CN114816532 A CN 114816532A CN 202210419942 A CN202210419942 A CN 202210419942A CN 114816532 A CN114816532 A CN 114816532A
- Authority
- CN
- China
- Prior art keywords
- register
- caller
- virtual
- function
- cost
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
- 238000000034 method Methods 0.000 title claims abstract description 33
- 238000004458 analytical method Methods 0.000 claims abstract description 7
- 230000006870 function Effects 0.000 claims description 124
- 230000006835 compression Effects 0.000 claims description 11
- 238000007906 compression Methods 0.000 claims description 11
- 238000005457 optimization Methods 0.000 claims description 9
- 239000003990 capacitor Substances 0.000 claims description 8
- 230000000694 effects Effects 0.000 claims description 4
- 238000012360 testing method Methods 0.000 description 5
- 238000011161 development Methods 0.000 description 2
- 238000005206 flow analysis Methods 0.000 description 2
- 230000009286 beneficial effect Effects 0.000 description 1
- 150000001875 compounds Chemical class 0.000 description 1
- 238000012217 deletion Methods 0.000 description 1
- 230000037430 deletion Effects 0.000 description 1
- 238000013461 design Methods 0.000 description 1
- 238000010586 diagram Methods 0.000 description 1
- 238000013507 mapping Methods 0.000 description 1
- 238000000638 solvent extraction Methods 0.000 description 1
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/30—Arrangements for executing machine instructions, e.g. instruction decode
- G06F9/38—Concurrent instruction execution, e.g. pipeline or look ahead
- G06F9/3836—Instruction issuing, e.g. dynamic instruction scheduling or out of order instruction execution
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/30—Arrangements for executing machine instructions, e.g. instruction decode
- G06F9/30145—Instruction analysis, e.g. decoding, instruction word fields
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/30—Arrangements for executing machine instructions, e.g. instruction decode
- G06F9/30181—Instruction operation extension or modification
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y02—TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
- Y02D—CLIMATE CHANGE MITIGATION TECHNOLOGIES IN INFORMATION AND COMMUNICATION TECHNOLOGIES [ICT], I.E. INFORMATION AND COMMUNICATION TECHNOLOGIES AIMING AT THE REDUCTION OF THEIR OWN ENERGY USE
- Y02D10/00—Energy efficient computing, e.g. low power processors, power management or thermal management
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Devices For Executing Special Programs (AREA)
Abstract
本发明公开了一种提高RISC‑V二进制代码密度的寄存器分配方法,目的是解决当前编译器的寄存器分配方法使代码密度降低的问题;技术方案是构建活跃变量寄存器分配代价模型,基于该模型计算当前分析虚拟寄存器指派给caller‑saved寄存器相对于指派给callee‑saved寄存器的代码密度收益,根据收益判断将跨函数调用中活跃变量对应的虚拟寄存器分配到caller‑saved还是callee‑saved寄存器更有利于减少指令条数,从而将当前被分析函数中跨函数调用的虚拟寄存器优先分配给caller‑saved或callee‑saved寄存器。采用本发明可减少编译生成的指令条数,提高二进制代码密度。
Description
技术领域
本发明涉及一种计算机编译领域的寄存器分配方法,尤指一种编译过程中能够提高RISC-V二进制代码密度的寄存器分配方法。
背景技术
目前,RISC-V指令集架构(其中RISC表示精简指令集计算机,全称ReducedInstruction Set Computer,RISC-V是基于RISC的一个开源指令集架构)以其开放、简洁、模块化等特点受到业界广泛关注,编译器对RISC-V指令集架构的支持直接影响到其发展与推广。二进制代码密度是衡量一款芯片特别是嵌入式芯片开发环境的重要指标之一,直接影响着嵌入式芯片的面积和成本。如何提高最终生成的二进制目标代码的代码密度一直是本领域技术人员极为关注的技术问题。
RISC-V指令集是模块化的指令集,以RV32I整数指令集为基础,根据不同的设计需求,可以通过扩展得到特定的扩展指令集:如RV32M(乘法指令集)、RV32F/RV32D(单精度/双精度浮点指令集)、RVC(压缩指令集)等。
为了提高二进制代码密度,一般指令集架构通常采用复合指令和压缩指令方式实现。而RISC-V指令集在常用标准操作中加入16位指令,即RISC-V压缩指令,以减少二进制代码长度。RISC-V压缩指令集中,每条16位压缩指令都和一条标准的32位指令一一对应。一条指令是否编码为压缩指令由汇编器和链接器决定,程序员编写汇编时可以完全忽略RISC-V压缩指令及其格式。
RISC-V压缩指令具有以下特点:
1)压缩指令的操作数是访问频率最高的十个常用寄存器(即RISC-V指令集架构中的a0-a5,s0-s1,sp以及ra);
2)压缩指令的目的操作数和源操作数是同一个寄存器;
3)压缩指令的立即数的位数很小,大部分指令只有6位立即数。
因此,在支持RISC-V压缩指令集(即RVC)的RISC-V平台(指采用RISC-V指令集架构的计算机系统)上,汇编生成的二进制代码长度大大缩短,代码密度比标准指令集有所提高。
处理器在运行软件程序时,变量必须存放在硬件寄存器。而每个变量应该存放在哪个硬件寄存器,由编译器在编译阶段进行分配,这个过程叫做编译器的寄存器分配。在生成中间代码的过程中,编译器首先假定有无限个虚拟寄存器用以存放临时变量,但是实际的机器体系结构中硬件寄存器是有限且少量的。因此,编译器寄存器分配的任务就是将大量的虚拟寄存器映射到机器实际的体系结构中的真实硬件寄存器上。编译器的寄存器分配是影响代码密度的关键因素。如何在寄存器分配过程中最大程度地减少代码溢出所产生的代价,是提高代码密度必须考虑的因素之一。现有编译器中的寄存器分配方法没有考虑到在RISC-V指令集架构上跨函数活跃变量的寄存器分配方案会导致不同的二进制指令数目的情况,不利于RISC-V二进制代码密度优化,具有优化空间。
一般来说,编译器会将跨函数调用活跃的临时变量分配到由被调用者保存的寄存器,此时编译器只需要在被调用函数的开始和结束处做一次保存和恢复该类寄存器即可;编译器会将局部变量或任何跨函数调用都不活跃的临时变量分配到由调用者保存的寄存器,由于局部变量或任何跨函数调用都不活跃的临时变量未跨任何函数调用,因此在这种情况下完全不需要保存和恢复这些寄存器。
在现有的通用编译平台中,根据RISC-V指令集架构的应用二进制接口ABI(application binary interface)规则,将RISC-V指令集架构的寄存器划分为调用者寄存器即caller-saved寄存器和被调用者寄存器即callee-saved寄存器。caller-saved寄存器是由调用者(Caller)保存的寄存器,当发生函数调用时,由调用者在函数调用前将此类寄存器保存至堆栈中,函数调用后恢复并使用;callee-saved寄存器是由被调用者(Callee)保存的寄存器,当发生函数调用时,由被调用者负责保存与恢复。
在通用编译平台中,caller-saved寄存器和callee-saved寄存器的划分如表1所示。根据表1中的ABI规则,参数寄存器a0~a7和临时寄存器t0~t6(浮点寄存器分别对应fa0~fa7和ft0~ft11)属于caller-saved寄存器,而寄存器s0~s11(浮点寄存器对应fs0~fs11)属于callee-saved的寄存器。表1中寄存器Type为“--”的表示该寄存器既不作为caller寄存器、也不作为callee寄存器使用。根据上述寄存器分配的规则,编译器将跨函数调用活跃的临时变量分配到s0~s11寄存器,并由编译器在被调用函数的开始和结束处分别生成保存和恢复该寄存器的代码;将局部变量或任何跨函数调用都不活跃的临时变量分配到a0~a7或t0~t6寄存器,编译器依据该临时变量在跨函数时是否活跃来决定是否保存和恢复该寄存器。
表1RISC-V指令集架构寄存器别名及函数调用规则
目前已有的编译器的RISC-V后端的寄存器分配方法是:将跨函数调用中的活跃变量对应的虚拟寄存器优先分配到callee-saved寄存器即s0-s11寄存器中,再将剩余的跨函数调用中的活跃变量对应的虚拟寄存器分配到caller-saved寄存器即a0-a7或t0-t6寄存器中。但是分配到这两种不同类型寄存器所生成的代码长度不同。比如,活跃变量在跨一个函数调用时,分配到caller-saved寄存器时,只需要生成sw指令(将寄存器中的值写入数据存储器)和lw指令(从数据存储器中取数据写进寄存器)两条指令,而分配到callee-saved寄存器则需要sw指令、lw指令和mv指令(为文件或目录改名或将文件由一个目录移入到另一个目录中)共三条指令,这样跟一个变量相关的代码将额外多出mv指令这4个字节。因此,跨函数调用中的活跃变量对于ing的虚拟寄存器分配到callee-saved寄存器或者caller-saved寄存器会给最终的二进制代码密度带来影响,但是现有的编译器的寄存器分配方法是固定的,即将跨函数活跃的变量对应的虚拟寄存器优先分配给callee-saved寄存器,如果callee-saved寄存器不可用了才分配到caller-saved寄存器,无法最优化地进行callee-saved寄存器或者caller-saved寄存器两种分配的选择,导致额外的指令操作,使得最终的程序代码密度降低。
发明内容
本发明要解决的技术问题是:针对现有编译器的RISC-V后端寄存器分配方法将跨函数调用中活跃变量对应的虚拟寄存器固定地优先分配到callee-saved寄存器,在某些情况下这将导致额外指令操作使得程序代码密度降低的问题,提出RISC-V代码密度优先的寄存器分配方法,采用该方法能够准确判断将跨函数调用中活跃变量对应的虚拟寄存器分配到caller-saved寄存器还是callee-saved寄存器更有利于减少指令条数,有效提高编译器生成的RISC-V二进制代码的密度。
本发明总体技术方案是:提出活跃变量寄存器分配代价模型,基于该代价模型对跨区域活跃变量的寄存器进行分配,从而减少编译生成的指令条数,提高编译器生成的二进制代码密度。
具体技术方案是:
第一步,构建活跃变量寄存器分配代价模型:
根据跨区域活跃变量不同寄存器的分配方式,构建以函数为单位的二进制代码密度代价公式即活跃变量寄存器分配代价模型,如下:
callee_cost(r)=callee_save_cost+callee_restore_cost+callee_move_costr∈所有待分配硬件寄存器的虚拟寄存器集合,公式(1);
caller_cost(r)=(caller_save_cost+caller_restore_cost)×n(r)+caller_move_cost r∈所有待分配硬件寄存器的虚拟寄存器集合,公式(2);
公式中caller_save_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到caller类寄存器时在跨函数调用前后或者函数开始和结束处保存寄存器的代价;callee_save_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到callee类寄存器时在跨函数调用前后或者函数开始和结束处保存寄存器的代价;caller_restore_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到caller类寄存器时在跨函数调用前后或者函数开始和结束处恢复寄存器的代价;callee_restore_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到callee类寄存器时在跨函数调用前后或者函数开始和结束处恢复寄存器的代价。在寄存器分配过程中,如果一个变量对应的虚拟寄存器已经被分配了寄存器,caller_move_cost表示在保存caller-saved寄存器之前,将已分配寄存器的变量的值放到caller-saved寄存器的代价;callee_move_cost表示在保存callee-saved寄存器之前,将已分配寄存器的变量的值放到callee-saved寄存器的代价。代价仅指对二进制代码密度的影响,不包括对二进制代码运行速度的影响。参数r为所有待分配硬件寄存器的虚拟寄存器中任意一个。n(r)是r跨函数调用活跃的次数。
公式(1)中callee_cost(r)表示分配callee-saved寄存器后编译器需要额外保存和恢复的代价。分配callee-saved寄存器不用考虑变量跨函数调用的活跃区间范围,仅需考虑在函数的开始和结束处保存和恢复寄存器的代价,以及已分配寄存器的变量的值放到callee-saved寄存器的代价。
公式(2)中caller_cost(r)表示分配caller-saved寄存器后编译器需要额外保存和恢复的代价。因为caller-saved寄存器每次在跨函数调用活跃时,都需要保存和恢复一次寄存器,因此,需要计算r跨函数调用活跃的次数,即n(r)的值;由于在开启编译器的-Os优化选项(当编译一个源程序,目的要获得较小的二进制代码的情况下,一定是会开启编译器的-Os优化选项)的前提下,变量的值放到caller-saved寄存器的操作将会在后续优化的寄存器重名和死代码删除中优化删除掉,在开启编译器的-Os优化的情况下caller_move_cost为0。
第二步,判定被编译程序的函数列表中有没有未进行寄存器分配的函数,若有,令函数列表中第一个未进行寄存器分配的函数为当前被分析函数,转第三步;若没有,转第九步;
第三步,分析当前被分析函数的每一条指令,建立第一指令链表和第二指令链表。将每条指令中所含虚拟寄存器的定值信息和活跃信息存储到第一指令链表中。第一指令链表中共有K个元素,K为当前被分析函数的指令中所含的虚拟寄存器个数;第k个元素包括当前被分析函数中第k个虚拟寄存器Rk、虚拟寄存器Rk的定值信息、虚拟寄存器Rk的活跃信息3个域,1≤k≤K。所述定值信息指虚拟寄存器的定值信息,所述活跃信息指虚拟寄存器的活跃信息。定值信息和活跃信息均是编译器在寄存器分配阶段的前一个阶段(数据流分析)生成的信息;将当前被分析函数中每一条call子调用的信息(主要包括每个call子调用所涉及到的虚拟寄存器)存储到第二指令链表中。第二指令链表共有P个元素,P为当前被分析函数中call子调用的个数;第p个元素包括当前被分析函数中第p个call子调用Cp,以及Cp所涉及到的虚拟寄存器。
第四步,将第一指令链表和第二指令链表进行对比,得到当前被分析函数中跨函数调用活跃的虚拟寄存器的个数N和这N个虚拟寄存器跨函数调用活跃的次数,构造跨函数调用活跃的虚拟寄存器列表,方法是:
4.1分析第一指令链表中的虚拟寄存器中哪些是跨函数调用活跃的虚拟寄存器。若第一指令链表中出现的虚拟寄存器同时出现在第二链表中,则该虚拟寄存器为跨函数调用活跃的虚拟寄存器。记跨函数调用活跃的虚拟寄存器的个数为N。
4.2在第二指令链表里寻找4.1获得的N个跨函数调用活跃的虚拟寄存器,这N个跨函数调用活跃的虚拟寄存器分别在第二指令链表中出现的次数即为当前被分析函数中这N个虚拟寄存器跨函数调用活跃的次数,令这N个跨函数调用活跃的虚拟寄存器中的第i个跨函数调用活跃的虚拟寄存器为Ri,则Ri跨函数调用活跃的次数为n(Ri);
4.3构造跨函数调用活跃的虚拟寄存器列表,跨函数调用活跃的虚拟寄存器列表包含N个表项,每个表项包含2个域,第i个表项的第一个域为虚拟寄存器名称Ri,第二个域为Ri跨函数调用活跃的次数n(Ri)。1≤i≤N。
第五步,令循环控制变量i=1;
第六步,若i≤N,将跨函数调用活跃的虚拟寄存器列表中第i个未分析的虚拟寄存器作为当前分析虚拟寄存器r,即令r=Ri,转第七步;若i>N,转第二步。
第七步,基于活跃变量寄存器分配代价模型计算当前分析虚拟寄存器指派给caller-saved寄存器的收益caller_benefit,并根据caller_benefit将当前被分析函数中跨函数调用的虚拟寄存器分配给caller-saved寄存器或callee-saved寄存器,方法是:
7.1若目标平台不支持压缩指令,转7.2;若目标平台支持压缩指令,转7.4;
7.2采用公式(3)计算当前被分析函数中跨函数调用的虚拟寄存器优先分配给caller-saved寄存器后能缩减代码空间的收益caller_benefit。
caller_benifit=callee_cost(r)-caller_cost(r)
r∈所有待分配寄存器组成的虚拟寄存器集合,公式(3)
7.3通过caller_benefit判断当前被分析函数中跨函数调用的虚拟寄存器是否应该优先分配给caller-saved寄存器,方法是:若caller_benefit≥零,表示优先分配给callee-saved寄存器的代价大于优先分配给caller-saved寄存器的代价,将当前虚拟寄存器优先指派给caller-saved寄存器;若caller_benefit<0,表示优先分配给callee-saved寄存器的代价小于优先分配给caller-saved寄存器的代价,将当前虚拟寄存器优先指派给callee-saved寄存器(编译器的默认操作)。转第八步;
7.4此时目标平台支持压缩指令,依据RVC压缩指令集的编码格式,当sw指令的rs2操作数为s0或s1,且lw指令的rd操作数为s0或s1寄存器时,sw指令和lw指令可以汇编生成16位压缩指令,因此在支持RVC压缩指令的32位架构中一个分配成s0或s1的callee-saved寄存器也能节省4个字节的代码空间。因此,若目标平台支持压缩指令,采用公式(4)计算在支持RVC压缩指令的RISC-V指令集架构中当前函数中跨函数调用的虚拟寄存器优先分配给caller-saved寄存器后能缩减代码空间的收益caller_benefit。
caller_benifit=callee_cost(r)-caller_cost(r),
r∈优先分配s0或s1后待分配寄存器的虚拟寄存器集合,公式(4)
7.5判断当前函数中跨函数调用的虚拟寄存器在优先分配s0或s1寄存器后是否应该再分配给caller-saved寄存器,方法是:如果caller_benifit≥零,表明所有跨函数调用的虚拟寄存器优先分配到callee-saved寄存器的代价大于等于分配到caller saved寄存器的代价,会使当前函数对应的二进制代码字节数减小,将当前虚拟寄存器优先指派给caller-saved寄存器;如果caller_benifit<零,则表明所有跨函数调用的虚拟寄存器优先分配到callee-saved寄存器的代价小于分配到caller-saved寄存器的代价,跨函数调用的虚拟寄存器不适合分配到caller-saved寄存器中,将当前虚拟寄存器优先指派给callee-saved寄存器(编译器的默认操作)。
第八步,令i=i+1,转第六步;
第九步,结束,输出对当前程序中所有函数中的跨函数调用活跃虚拟寄存器的寄存器分配结果,即每个跨函数调用活跃虚拟寄存器应优先分配给caller-saved寄存器还是优先分配给callee-saved寄存器的结果。
采用本发明可以达到以下技术效果:
本发明结合RISC-V指令集的特点(涉及到sw指令、lw指令、mv指令等,以及RISC-V压缩指令集)和编译器针对RISC-V指令集架构的寄存器分配方案的不足,基于活跃变量寄存器分配代价模型进行寄存器分配,可减少编译生成的指令条数,提高生成的二进制代码密度。
附图说明
图1是本发明总体流程图。
图2是使用本发明的llvm编译器和未使用本发明的llvm编译器编译replaypc-0.4.0测试套件中的31个测试程序所生成二进制代码密度的提升比例柱状图。
具体实施方式
如图1所示,本发明包括以下步骤:
第一步,构建活跃变量寄存器分配代价模型:
根据跨区域活跃变量不同寄存器的分配方式,构建以函数为单位的二进制代码密度代价公式即活跃变量寄存器分配代价模型,如下:
callee_cost(r)=callee_save_cost+callee_restore_cost+callee_move_costr∈所有待分配硬件寄存器的虚拟寄存器集合,公式(1);
caller_cost(r)=(caller_save_cost+caller_restore_cost)×n(r)+caller_move_cost r∈所有待分配硬件寄存器的虚拟寄存器集合,公式(2);
公式中caller_save_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到caller类寄存器时在跨函数调用前后或者函数开始和结束处保存寄存器的代价;callee_save_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到callee类寄存器时在跨函数调用前后或者函数开始和结束处保存寄存器的代价;caller_restore_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到caller类寄存器时在跨函数调用前后或者函数开始和结束处恢复寄存器的代价;callee_restore_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到callee类寄存器时在跨函数调用前后或者函数开始和结束处恢复寄存器的代价。caller_move_cost表示在保存caller-saved寄存器之前,将已分配寄存器的变量的值放到caller-saved寄存器的代价;callee_move_cost表示在保存callee-saved寄存器之前,将已分配寄存器的变量的值放到callee-saved寄存器的代价。参数r为所有待分配硬件寄存器的虚拟寄存器中任意一个。n(r)是r跨函数调用活跃的次数。
公式(1)中callee_cost(r)表示分配callee-saved寄存器后编译器需要额外保存和恢复的代价。公式(2)中caller_cost(r)表示分配caller-saved寄存器后编译器需要额外保存和恢复的代价。在开启编译器的-Os优化的情况下caller_move_cost为0。
第二步,判定被编译程序的函数列表中有没有未进行寄存器分配的函数,若有,令函数列表中第一个未进行寄存器分配的函数为当前被分析函数,转第三步;若没有,转第九步;
第三步,分析当前被分析函数的每一条指令,建立第一指令链表和第二指令链表。将每条指令中所含虚拟寄存器的定值信息和活跃信息存储到第一指令链表中。第一指令链表中共有K个元素,K为当前被分析函数的指令中所含的虚拟寄存器个数;第k个元素包括当前被分析函数中第k个虚拟寄存器Rk、虚拟寄存器Rk的定值信息、虚拟寄存器Rk的活跃信息3个域,1≤k≤K。所述定值信息指虚拟寄存器的定值信息,所述活跃信息指虚拟寄存器的活跃信息。定值信息和活跃信息均是编译器在寄存器分配阶段的前一个阶段(数据流分析)生成的信息;将当前被分析函数中每一条call子调用的信息(主要包括每个call子调用所涉及到的虚拟寄存器)存储到第二指令链表中。第二指令链表共有P个元素,P为当前被分析函数中call子调用的个数;第p个元素包括当前被分析函数中第p个call子调用Cp,以及Cp所涉及到的虚拟寄存器。
第四步,将第一指令链表和第二指令链表进行对比,得到当前被分析函数中跨函数调用活跃的虚拟寄存器的个数N和这N个虚拟寄存器跨函数调用活跃的次数,构造跨函数调用活跃的虚拟寄存器列表,方法是:
4.1分析第一指令链表中的虚拟寄存器中哪些是跨函数调用活跃的虚拟寄存器。若第一指令链表中出现的虚拟寄存器同时出现在第二链表中,则该虚拟寄存器为跨函数调用活跃的虚拟寄存器。记跨函数调用活跃的虚拟寄存器的个数为N。
4.2在第二指令链表里寻找4.1获得的N个跨函数调用活跃的虚拟寄存器,这N个跨函数调用活跃的虚拟寄存器分别在第二指令链表中出现的次数即为当前被分析函数中这N个虚拟寄存器跨函数调用活跃的次数,令这N个跨函数调用活跃的虚拟寄存器中的第i个跨函数调用活跃的虚拟寄存器为Ri,则Ri跨函数调用活跃的次数为n(Ri);
4.3构造跨函数调用活跃的虚拟寄存器列表,跨函数调用活跃的虚拟寄存器列表包含N个表项,每个表项包含2个域,第i个表项的第一个域为虚拟寄存器名称Ri,第二个域为Ri跨函数调用活跃的次数n(Ri)。1≤i≤N。
第五步,令循环控制变量i=1;
第六步,若i≤N,将跨函数调用活跃的虚拟寄存器列表中第i个未分析的虚拟寄存器作为当前分析虚拟寄存器r,即令r=Ri,转第七步;若i>N,转第二步。
第七步,基于活跃变量寄存器分配代价模型计算当前分析虚拟寄存器指派给caller-saved寄存器的收益caller_benefit,并根据caller_benefit将当前被分析函数中跨函数调用的虚拟寄存器分配给caller-saved寄存器或callee-saved寄存器,方法是:
7.1若目标平台不支持压缩指令,转7.2;若目标平台支持压缩指令,转7.4;
7.2采用公式(3)计算当前被分析函数中跨函数调用的虚拟寄存器优先分配给caller-saved寄存器后能缩减代码空间的收益caller_benefit。
caller_benifit=callee_cost(r)-caller_cost(r)
r∈所有待分配寄存器组成的虚拟寄存器集合,公式(3)
7.3通过caller_benefit判断当前被分析函数中跨函数调用的虚拟寄存器是否应该优先分配给caller-saved寄存器,方法是:若caller_benefit≥零,表示优先分配给callee-saved寄存器的代价大于优先分配给caller-saved寄存器的代价,将当前虚拟寄存器优先指派给caller-saved寄存器;若caller_benefit<0,表示优先分配给callee-saved寄存器的代价小于优先分配给caller-saved寄存器的代价,将当前虚拟寄存器优先指派给callee-saved寄存器(编译器的默认操作)。转第八步;
7.4此时目标平台支持压缩指令,依据RVC压缩指令集的编码格式,当sw指令的rs2操作数为s0或s1,且lw指令的rd操作数为s0或s1寄存器时,sw指令和lw指令可以汇编生成16位压缩指令,因此在支持RVC压缩指令的32位架构中一个分配成s0或s1的callee-saved寄存器也能节省4个字节的代码空间。因此,若目标平台支持压缩指令,采用公式(4)计算在支持RVC压缩指令的RISC-V指令集架构中当前函数中跨函数调用的虚拟寄存器优先分配给caller-saved寄存器后能缩减代码空间的收益caller_benefit。
caller_benifit=callee_cost(r)-caller_cost(r),
r∈优先分配s0或s1后待分配寄存器的虚拟寄存器集合,公式(4)
7.5判断当前函数中跨函数调用的虚拟寄存器在优先分配s0或s1寄存器后是否应该再分配给caller-saved寄存器,方法是:如果caller_benifit≥零,表明所有跨函数调用的虚拟寄存器优先分配到callee-saved寄存器的代价大于等于分配到caller saved寄存器的代价,会使当前函数对应的二进制代码字节数减小,将当前虚拟寄存器优先指派给caller-saved寄存器;如果caller_benifit<零,则表明所有跨函数调用的虚拟寄存器优先分配到callee-saved寄存器的代价小于分配到caller-saved寄存器的代价,跨函数调用的虚拟寄存器不适合分配到caller-saved寄存器中,将当前虚拟寄存器优先指派给callee-saved寄存器(编译器的默认操作)。
第八步,令i=i+1,转第六步;
第九步,结束,输出对当前程序中所有函数中的跨函数调用活跃虚拟寄存器的寄存器分配结果,即每个跨函数调用活跃虚拟寄存器应优先分配给caller-saved寄存器还是优先分配给callee-saved寄存器的结果。
为了验证本发明的效果,将本发明应用于llvm-10.0编译器,生成了基于本发明的RISC-V指令集架构的llvm编译器。采用该编译器,对标准的benchmark工具CSiBE(GCCCode-Size Benchmark Environment)中的replaypc-0.4.0测试套件中的31个测试程序进行实验。在开启“-Os”优化选项的情况下,对比未采用本发明的llvm-10.0编译器,对生成的二进制代码密度进行对比,结果如图2所示,柱状图表示各个源文件编译生成二进制文件后代码密度的提升比例,可以看出,源程序dump-programset和find-GOPs提升比例较大(因为这2个程序跨函数调用活跃的变量比较多),分别达到了11.33%和12.17%,而其他源程序对应的提升也达到了0.1-10%。因此本发明对于RISC-V二进制代码的代码密度提高具有明显效果。
Claims (3)
1.一种提高RISC-V二进制代码密度的寄存器分配方法,其特征在于提出活跃变量寄存器分配代价模型,基于该代价模型对跨区域活跃变量的寄存器进行分配;包括以下步骤:
第一步,构建活跃变量寄存器分配代价模型:
根据跨区域活跃变量不同寄存器的分配方式,构建以函数为单位的二进制代码密度代价公式即活跃变量寄存器分配代价模型,如下:
callee_cost(r)=callee_save_cost+callee_restore_cost+callee_move_cost r∈所有待分配硬件寄存器的虚拟寄存器集合,公式(1);
caller_cost(r)=(caller_save_cost+caller_restore_cost)×n(r)+caller_move_cost r∈所有待分配硬件寄存器的虚拟寄存器集合,公式(2);
caller_save_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到caller类寄存器时在跨函数调用前后或者函数开始和结束处保存寄存器的代价;callee_save_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到callee类寄存器时在跨函数调用前后或者函数开始和结束处保存寄存器的代价;caller_restore_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到caller类寄存器时在跨函数调用前后或者函数开始和结束处恢复寄存器的代价;callee_restore_cost表示当把跨区域活跃变量对应的虚拟寄存器分配到callee类寄存器时在跨函数调用前后或者函数开始和结束处恢复寄存器的代价;caller_move_cost表示在保存caller-saved寄存器之前,将已分配寄存器的变量的值放到caller-saved寄存器的代价;callee_move_cost表示在保存callee-saved寄存器之前,将已分配寄存器的变量的值放到callee-saved寄存器的代价;代价指对二进制代码密度的影响;参数r为所有待分配硬件寄存器的虚拟寄存器中任意一个;n(r)是r跨函数调用活跃的次数;
callee_cost(r)表示分配callee-saved寄存器后编译器需要额外保存和恢复的代价;caller_cost(r)表示分配caller-saved寄存器后编译器需要额外保存和恢复的代价;
第二步,判定被编译程序的函数列表中有没有未进行寄存器分配的函数,若有,令函数列表中第一个未进行寄存器分配的函数为当前被分析函数,转第三步;若没有,转第九步;
第三步,分析当前被分析函数的每一条指令,建立第一指令链表和第二指令链表;将每条指令中所含虚拟寄存器的定值信息和活跃信息存储到第一指令链表中;第一指令链表中共有K个元素,K为当前被分析函数的指令中所含的虚拟寄存器个数;第k个元素包括当前被分析函数中第k个虚拟寄存器Rk、虚拟寄存器Rk的定值信息、虚拟寄存器Rk的活跃信息3个域,1≤k≤K;所述定值信息指虚拟寄存器的定值信息,所述活跃信息指虚拟寄存器的活跃信息;将当前被分析函数中每一条call子调用的信息即每个call子调用所涉及到的虚拟寄存器存储到第二指令链表中;第二指令链表共有P个元素,P为当前被分析函数中call子调用的个数;第p个元素包括当前被分析函数中第p个call子调用Cp,以及Cp所涉及到的虚拟寄存器;
第四步,将第一指令链表和第二指令链表进行对比,得到当前被分析函数中跨函数调用活跃的虚拟寄存器的个数N和这N个虚拟寄存器跨函数调用活跃的次数,构造跨函数调用活跃的虚拟寄存器列表,跨函数调用活跃的虚拟寄存器列表包含N个表项,每个表项包含2个域,第i个表项的第一个域为虚拟寄存器名称Ri,第二个域为Ri跨函数调用活跃的次数n(Ri);1≤i≤N;
第五步,令循环控制变量i=1;
第六步,若i≤N,将跨函数调用活跃的虚拟寄存器列表中第i个未分析的虚拟寄存器作为当前分析虚拟寄存器r,即令r=Ri,转第七步;若i>N,转第二步;
第七步,基于活跃变量寄存器分配代价模型计算当前分析虚拟寄存器指派给caller-saved寄存器的收益caller_benefit,并根据caller_benefit将当前被分析函数中跨函数调用的虚拟寄存器分配给caller-saved寄存器或callee-saved寄存器,方法是:
7.1若目标平台不支持压缩指令,转7.2;若目标平台支持压缩指令,转7.4;
7.2采用公式(3)计算当前被分析函数中跨函数调用的虚拟寄存器优先分配给caller-saved寄存器后能缩减代码空间的收益caller_benefit;
caller_benifit=callee_cost(r)-caller_cost(r)
r∈所有待分配寄存器组成的虚拟寄存器集合,公式(3)
7.3通过caller_benefit判断当前被分析函数中跨函数调用的虚拟寄存器是否应该优先分配给caller-saved寄存器,方法是:若caller_benefit≥零,表示优先分配给callee-saved寄存器的代价大于优先分配给caller-saved寄存器的代价,将当前虚拟寄存器优先指派给caller-saved寄存器;若caller_benefit<0,将当前虚拟寄存器优先指派给callee-saved寄存器;转第八步;
7.4采用公式(4)计算在支持RVC压缩指令的RISC-V指令集架构中当前函数中跨函数调用的虚拟寄存器优先分配给caller-saved寄存器后能缩减代码空间的收益caller_benefit;
caller_benifit=callee_cost(r)-caller_cost(r),
r∈优先分配s0或s1后待分配寄存器的虚拟寄存器集合,公式(4)
7.5判断当前函数中跨函数调用的虚拟寄存器在优先分配s0或s1寄存器后是否应该再分配给caller-saved寄存器,方法是:如果caller_benifit≥零,将当前虚拟寄存器优先指派给caller-saved寄存器;如果caller_benefit<零,将当前虚拟寄存器优先指派给callee-saved寄存器;
第八步,令i=i+1,转第六步;
第九步,结束,输出对当前程序中所有函数中的跨函数调用活跃虚拟寄存器的寄存器分配结果,即每个跨函数调用活跃虚拟寄存器应优先分配给caller-saved寄存器还是优先分配给callee-saved寄存器的结果。
2.如权利要求1所述的一种提高RISC-V二进制代码密度的寄存器分配方法,其特征在于第一步公式(2)中所述caller_move_cost在开启编译器的-Os优化的情况下为0。
3.如权利要求1所述的一种提高RISC-V二进制代码密度的寄存器分配方法,其特征在于第四步所述将第一指令链表和第二指令链表进行对比,得到当前被分析函数中跨函数调用活跃的虚拟寄存器的个数N和这N个虚拟寄存器跨函数调用活跃的次数的方法是:
3.1分析第一指令链表中的虚拟寄存器中哪些是跨函数调用活跃的虚拟寄存器;若第一指令链表中出现的虚拟寄存器同时出现在第二链表中,则该虚拟寄存器为跨函数调用活跃的虚拟寄存器;记跨函数调用活跃的虚拟寄存器的个数为N;
3.2在第二指令链表里寻找3.1获得的N个跨函数调用活跃的虚拟寄存器,这N个跨函数调用活跃的虚拟寄存器分别在第二指令链表中出现的次数即为当前被分析函数中这N个虚拟寄存器跨函数调用活跃的次数,令这N个跨函数调用活跃的虚拟寄存器中的第i个跨函数调用活跃的虚拟寄存器为Ri,则Ri跨函数调用活跃的次数为n(Ri)。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202210419942.8A CN114816532B (zh) | 2022-04-20 | 2022-04-20 | 一种提高risc-v二进制代码密度的寄存器分配方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202210419942.8A CN114816532B (zh) | 2022-04-20 | 2022-04-20 | 一种提高risc-v二进制代码密度的寄存器分配方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN114816532A true CN114816532A (zh) | 2022-07-29 |
CN114816532B CN114816532B (zh) | 2023-04-04 |
Family
ID=82505666
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202210419942.8A Active CN114816532B (zh) | 2022-04-20 | 2022-04-20 | 一种提高risc-v二进制代码密度的寄存器分配方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN114816532B (zh) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN115617396A (zh) * | 2022-10-09 | 2023-01-17 | 上海燧原科技有限公司 | 应用于新型人工智能处理器的寄存器分配方法及装置 |
Citations (10)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
GB0028079D0 (en) * | 2000-11-17 | 2001-01-03 | Imperial College | System and method |
CN1303501A (zh) * | 1998-05-27 | 2001-07-11 | Arm有限公司 | 混合向量/标量寄存器文件 |
US20020056024A1 (en) * | 1999-02-26 | 2002-05-09 | Tuan H. Bui | Processor with register stack engine that dynamically spills/fills physical registers to backing store |
US20040133766A1 (en) * | 2003-01-08 | 2004-07-08 | Abraham Santosh G. | Method and apparatus for dynamically allocating registers in a windowed architecture |
CN101216774A (zh) * | 2008-01-03 | 2008-07-09 | 中国科学院计算技术研究所 | 一种使用空闲寄存器类作为快速溢出空间的优化方法 |
CN102221994A (zh) * | 2010-04-19 | 2011-10-19 | 微软公司 | 用于改变回复力的中间语言支持 |
CN102880449A (zh) * | 2012-09-18 | 2013-01-16 | 中国科学院声学研究所 | 一种超长指令字结构下延迟槽调度方法及其系统 |
CN111435309A (zh) * | 2019-01-11 | 2020-07-21 | 中标软件有限公司 | 一种寄存器分配优化实现方法 |
CN111767080A (zh) * | 2019-03-30 | 2020-10-13 | 英特尔公司 | 用于可配置空间加速器中的操作的设备、方法和系统 |
CN112445484A (zh) * | 2019-08-27 | 2021-03-05 | 龙芯中科技术股份有限公司 | 一种寄存器处理方法、装置、电子设备及存储介质 |
-
2022
- 2022-04-20 CN CN202210419942.8A patent/CN114816532B/zh active Active
Patent Citations (10)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1303501A (zh) * | 1998-05-27 | 2001-07-11 | Arm有限公司 | 混合向量/标量寄存器文件 |
US20020056024A1 (en) * | 1999-02-26 | 2002-05-09 | Tuan H. Bui | Processor with register stack engine that dynamically spills/fills physical registers to backing store |
GB0028079D0 (en) * | 2000-11-17 | 2001-01-03 | Imperial College | System and method |
US20040133766A1 (en) * | 2003-01-08 | 2004-07-08 | Abraham Santosh G. | Method and apparatus for dynamically allocating registers in a windowed architecture |
CN101216774A (zh) * | 2008-01-03 | 2008-07-09 | 中国科学院计算技术研究所 | 一种使用空闲寄存器类作为快速溢出空间的优化方法 |
CN102221994A (zh) * | 2010-04-19 | 2011-10-19 | 微软公司 | 用于改变回复力的中间语言支持 |
CN102880449A (zh) * | 2012-09-18 | 2013-01-16 | 中国科学院声学研究所 | 一种超长指令字结构下延迟槽调度方法及其系统 |
CN111435309A (zh) * | 2019-01-11 | 2020-07-21 | 中标软件有限公司 | 一种寄存器分配优化实现方法 |
CN111767080A (zh) * | 2019-03-30 | 2020-10-13 | 英特尔公司 | 用于可配置空间加速器中的操作的设备、方法和系统 |
CN112445484A (zh) * | 2019-08-27 | 2021-03-05 | 龙芯中科技术股份有限公司 | 一种寄存器处理方法、装置、电子设备及存储介质 |
Non-Patent Citations (2)
Title |
---|
GUEI-YUAN LUEH等: "Call-cost directed register allocation", 《ACM》 * |
谢依伦: "基于LLVM的RISC-Ⅴ代码密度优化算法", 《中国优秀硕士论文电子期刊网 信息科技辑》 * |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN115617396A (zh) * | 2022-10-09 | 2023-01-17 | 上海燧原科技有限公司 | 应用于新型人工智能处理器的寄存器分配方法及装置 |
CN115617396B (zh) * | 2022-10-09 | 2023-08-29 | 上海燧原科技有限公司 | 应用于新型人工智能处理器的寄存器分配方法及装置 |
Also Published As
Publication number | Publication date |
---|---|
CN114816532B (zh) | 2023-04-04 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
EP1280056B1 (en) | Generation of debugging information | |
KR100518584B1 (ko) | 공유 라이브러리 시스템 및 상기 시스템 구축 방법 | |
US6021273A (en) | Interpreter generation and implementation utilizing interpreter states and register caching | |
EP1114366B1 (en) | Accurate method for inlining virtual calls | |
US20030149963A1 (en) | Condition code flag emulation for program code conversion | |
US7412710B2 (en) | System, method, and medium for efficiently obtaining the addresses of thread-local variables | |
US6658657B1 (en) | Method and apparatus for reducing the overhead of virtual method invocations | |
JPH02272627A (ja) | デイジタル・コンピユータ・システムとその手続呼び出し方法 | |
JPH10198570A (ja) | 読み出し専用メモリにクラスをロードする方法及びシステム | |
JP2002527815A (ja) | プログラムコード変換方法 | |
US5960197A (en) | Compiler dispatch function for object-oriented C | |
US7028293B2 (en) | Constant return optimization transforming indirect calls to data fetches | |
US6119206A (en) | Design of tags for lookup of non-volatile registers | |
US7552313B2 (en) | VLIW digital signal processor for achieving improved binary translation | |
US5901314A (en) | Method for reducing the size of computer programs | |
CN114816532B (zh) | 一种提高risc-v二进制代码密度的寄存器分配方法 | |
US7032230B2 (en) | Efficient virtual function calls for compiled/interpreted environments | |
Nelson | A comparison of PASCAL intermediate languages | |
US6901591B1 (en) | Frameworks for invoking methods in virtual machines | |
US7356812B2 (en) | Passing parameters by implicit reference | |
US6968549B1 (en) | Method and system for dynamically loading data structures into memory with global constant pool | |
US20090328020A1 (en) | Interface optimization in a closed system | |
US20080282071A1 (en) | Microprocessor and register saving method | |
JP2002182926A (ja) | コンパイル方法及びコンピュータ読み取り可能な記録媒体 | |
US8839274B2 (en) | Accelerated class check |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |