建立虚拟寄存器生存区间的方法和装置及编译方法和装置
文献发布时间:2023-06-19 11:19:16
技术领域
本申请涉及计算技术领域,具体而言,涉及一种建立虚拟寄存器生存区间的方法和装置及编译方法和装置、电子设备和计算机可读介质。
背景技术
在芯片体系结构中,一般存在多种寄存器,例如标量寄存器和向量寄存器。在针对某种体系结构的芯片进行代码编译时,需要完成的任务之一就是寄存器分配。寄存器分配是通过将程序虚拟寄存器尽可能地分配到寄存器,从而提高程序执行速度的一种方法。寄存器分配是编译器优化中最为重要的问题之一,好的寄存器分配能够大大提高程序执行速度(超过250%)。寄存器分配涉及到生存区间或冲突图(对于图着色类算法的分配器)的建立。
在所述背景技术部分公开的上述信息仅用于加强对本申请的背景的理解,因此它可以包括不构成对本领域普通技术人员已知的现有技术的信息。
发明内容
本申请旨在提供一种分配寄存器的方法和装置及编译方法和装置及电子设备,能够提高代码执行性能。
本申请的其该用户特性和优点将通过下面的详细描述变得显然,或部分地通过本申请的实践而习得。
根据本申请的一方面,提供一种建立虚拟寄存器生存区间的方法,包括:
获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令;
为所述指令按顺序建立递增或递减的程序点编号;
利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间;
在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间,并为所述第一类型溢出区间建立第一类型溢出点编号;
在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间,并为所述第二类型溢出区间建立第二类型溢出点编号,
其中,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。
根据本申请的另一方面,提供一种用于编译的方法,包括:
获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令;
为所述指令按顺序建立递增或递减的程序点编号;
利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间;
为所述第一类型虚拟寄存器的生存区间分配第一类型寄存器;
在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器,为所述第一类型溢出区间建立第一类型溢出点编号;
为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器以及为所述增加的第二类型虚拟寄存器的生存区间分配第二类型寄存器;
在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间以用于增加第二类型溢出伪指令,为所述第二类型溢出区间建立第二类型溢出点编号,
其中,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容,且
其中,所述第一类型寄存器的宽度大于所述第二类型寄存器的宽度。
根据本申请的另一方面,提供一种电子设备,包括:一个或多个处理单元;存储单元,用于存储一个或多个程序;当所述一个或多个程序被所述一个或多个处理器执行,使得所述一个或多个处理器实现前述的方法。
根据本申请的另一方面,提供一种计算机可读介质,其上存储有计算机程序,所述程序被处理器执行时实现前述的方法。
根据本申请实施例,根据示例实施例,将程序点编号融入通常使用的生存区间分析中,构成统一的生存区间表示方式,这种生存区间表示方式和分析流程结合,能减少编译时间,同时产生更高质量的目标代码。
应当理解的是,以上的一般描述和后文的细节描述仅是示例性的,并不能限制本申请。
附图说明
通过参照附图详细描述其示例实施例,本申请的上述和其它目标、特征及优点将变得更加显而易见。
图1A示出图着色算法分配寄存器的示例。
图1B示出线性扫描算法分配寄存器的示例。
图2示出根据本申请示例实施例的建立虚拟寄存器生存区间的方法。
图3示出根据本申请示例实施例的编译方法。
图4示出根据本申请示例实施例的分配寄存器的方法。
图5示出根据本申请另一示例实施例的分配寄存器的方法。
图6示出根据本申请示例实施例的建立虚拟寄存器生存区间的装置。
图7示出根据本申请示例实施例的编译装置。
图8示出根据本申请示例实施例的电子设备的框图。
具体实施方式
现在将参考附图更全面地描述示例实施例。然而,示例实施例能够以多种形式实施,且不应被理解为限于在此阐述的实施例;相反,提供这些实施例使得本申请将全面和完整,并将示例实施例的构思全面地传达给本领域的技术人员。在图中相同的附图标记表示相同或类似的部分,因而将省略对它们的重复描述。
此外,所描述的特征、结构或特性可以以任何合适的方式结合在一个或更多实施例中。在下面的描述中,提供许多具体细节从而给出对本申请的实施例的充分理解。然而,本领域技术人员将意识到,可以实践本申请的技术方案而没有特定细节中的一个或更多,或者可以采用其它的方法、组元、装置、步骤等。在其它情况下,不详细示出或描述公知方法、装置、实现或者操作以避免模糊本申请的各方面。
附图中所示的方框图仅仅是功能实体,不一定必须与物理上独立的实体相对应。即,可以采用软件形式来实现这些功能实体,或在一个或多个硬件模块或集成电路中实现这些功能实体,或在不同网络和/或处理器装置和/或微控制器装置中实现这些功能实体。
附图中所示的流程图仅是示例性说明,不是必须包括所有的内容和操作/步骤,也不是必须按所描述的顺序执行。例如,有的操作/步骤还可以分解,而有的操作/步骤可以合并或部分合并,因此实际执行的顺序有可能根据实际情况改变。
本申请的说明书和权利要求书及上述附图中的术语“第一”、“第二”等是用于区别不同对象,而不是用于描述特定顺序。此外,术语“包括”和“具有”以及它们任何变形,意图在于覆盖不排他的包含。例如包含了一系列步骤或单元的过程、方法、系统、产品或设备没有限定于已列出的步骤或单元,而是可选地还包括没有列出的步骤或单元,或可选地还包括对于这些过程、方法、产品或设备固有的其他步骤或单元。
在本文中提及“实施例”意味着,结合实施例描述的特定特征、结构或特性可以包含在本申请的至少一个实施例中。在说明书中的各个位置出现该短语并不一定均是指相同的实施例,也不是与其它实施例互斥的独立的或备选的实施例。本领域技术人员可以理解的是,本文所描述的实施例可以与其它实施例相结合。
在描述本申请实施例之前,对本申请实施例涉及到的一些术语进行解释说明。
编译:编译是将一种中间表示(IR)转换成另外一种IR。编译分为前端、中端和后端。后端得到的目标代码与目标体系结构紧密相关。
标量寄存器:用于完成标量计算的寄存器。
向量寄存器:用于特殊目的的寄存器,一般来说比标量寄存器更宽,可以看成有固定数目的几个标量寄存器组成。
物理寄存器:目标体系结构中实际存在的寄存器,可以包括标量寄存器和向量寄存器。
中间表示(IR:intermediate representation):编译器通常组织为一连串的处理趟(pass),随着编译器不断推导有关被编译代码的知识,必须将这些信息从一趟传递到另一趟。因而,对于推导出有关程序的全部事实,编译器需要一种表示,这种表示称为中间表示,简称为IR。IR可包括伪指令。IR分为多层。较高层(比较抽象)的IR可能没有虚拟寄存器的概念,只有变量的概念;而较底层(比较具体、更贴近目标机器)的IR可能没有变量的概念,只有虚拟与物理寄存器的概念。
虚拟寄存器:在编译过程中源文件中的操作数的一个编号。从较高层IR转换为较底层IR的过程中,“变量”的概念会被映射为“虚拟寄存器”的概念。因此,在本申请中,虚拟寄存器和变量可混用,具有相同的含义,本领域技术人员可根据上下文理解其使用。“虚拟寄存器”可以有无限多个,但最终要被映射到目标机器上有限多个物理寄存器上。
寄存器分配:将虚拟寄存器映射到物理寄存器的过程。在针对某种体系结构的处理器进行代码编译时,寄存器分配是通过将虚拟寄存器尽可能地分配到寄存器(物理寄存器),即,使尽可能多的变量驻留寄存器,从而提高程序执行速度的一种方法。寄存器分配过程可以理解为将虚拟寄存器和物理寄存器间建立多对一的映射关系。寄存器分配是编译中最为重要的任务之一,好的寄存器分配能够大大提高程序执行速度。
溢出:寄存器分配时,物理寄存器数量不够时,将当前寄存器中的值放置到其他地址空间上(通常是栈),在使用时再从其他地址空间上取回。一般来说寄存器溢出到栈上比较缓慢,不同寄存器之间的移动速度更快。简单的溢出(spill)算法是这样的:对于某个被选择溢出的生存区间的变量,在其每一个定义之后插入一条store指令,在其每一个使用之前插入一个load指令。显然,这个算法会插入大量的冗余的store和load指令。
程序点:IR表示中,指令两边的位置点称为程序点,可通过编号来表示和区分。
生存区间:假设IR里的指令按顺序(例如,中间表示中伪指令出现的顺序)编号,有时也称为程序点编号,变量v的生存区间是区间[i,j],则表明:不存在编号为j1(j1>j)的指令,使得变量v在j1处活跃,且不存在编号为i1(i1
数据流分析:数据流分析是一项编译时使用的技术,它能从程序代码中收集程序的语义信息,并通过代数的方法在编译时确定变量的定义和使用(def-use)。利用数据流分析可获得变量的存活信息,即在给定的程序点,哪些变量是“存活”的。存活信息给出了生存区间的线索,从而通过扫描中间表示的程序点可容易地建立变量的生存区间。通过数据流分析,可以不必实际运行程序就能够发现程序运行时的行为,这样可以帮助大家理解程序。数据流分析被用于解决编译优化、程序验证、调试、测试、并行、向量化和片行编程环境等问题。
图着色算法:寄存器分配问题被抽象成图着色问题,图中的每个节点代表某个变量的生命期,生命期是从变量第一次被定义(赋值)开始,到它下一次被赋值前的最后一次被使用为止。两个节点之间的边表示这两个变量生存区间因为存在重叠导致互相冲突或干涉。一般说来,如果两个变量在函数的某一点是同时存活的,则它们相互冲突,不能占有同一个寄存器。为了使用图着色算法,要构造冲突图,图中的节点代表生存区间,边代表冲突关系。两个节点之间没有边相连,则可以分配到同一个寄存器。例如图1A中,图1A示出为6个变量(a-f)分配4个寄存器(r0-r3)而不产生冲突。
线性扫描算法:线性扫描算法基于变量的生存区间分配寄存器。线性扫描算法按变量生存区间的起点顺序存储所有变量,同时按变量生存区间的终点顺序存储当前分配有(占用)寄存器的变量。变量区间的重叠数目只有在遇到某个变量生存区间的起点和终点时才发生改变,因此扫描到出现新的变量生存区间时考虑如何为它分配寄存器。当一个变量生存区间的终点早于另一个变量生存区间的起点,则这个变量分配的寄存器可被释放而重新分配给另一个变量。图1B示出为5个变量的生存区间分配2个寄存器的例子,其中A-E表示变量,变量右边的横线表示生存区间,数字1-5表示线性扫描算法分配寄存器的步骤。由图可见,在步骤1,为变量A的生存区间分配一个寄存器。在步骤2,为变量B的生存区间分配一个寄存器,这时分配有寄存器的是变量A和B的两个生存区间。在步骤3,由于没有可供分配的寄存器,因此变量C溢出。在步骤4,由于分配给A的寄存器可被释放,因此该寄存器重新分配给变量D的生存区间,这时分配有寄存器的是变量D和B的两个生存区间。在步骤5,由于分配给B的寄存器可被释放,因此该寄存器重新分配给变量E的生存区间,这时分配有寄存器的是变量D和E的两个生存区间。
下面对本申请的技术方案进行详细说明。
对于多寄存器体系结构,例如同时包括向量寄存器和标量寄存器的计算体系结构中,存在两种常见的寄存器分配方式,第一种是对各种寄存器单独分配,第二种是将各种寄存器混合分配。
第一种方式实现起来较简单,其利用不同寄存器分配过程的相似性,可推广到所有的体系结构。以包括标量寄存器和向量寄存器的体系结构为例,第一种方式的主要思想是基于不同寄存器分配过程的相似性,将所有类型的寄存器都当作标量寄存器进行处理,只有在某些需要特殊处理的时候才特别处理。
第二种方式相比于第一种方式在某些体系结构中能够产生更高性能的代码并且需要的编译时间更短。仍以包括标量寄存器和向量寄存器的体系结构为例,这种方式在没有发生溢出之前将向量寄存器也看作标量寄存器,使用同样的方式在各自寄存器内部分配。一旦发生溢出行为,虚拟标量寄存器就会被溢出到栈上,而虚拟向量寄存器则会先行溢出到标量寄存器。插入溢出代码,并且引入新的虚拟标量寄存器待分配,整个过程构成一个循环,直到队列中不再有需要分配的虚拟寄存器为止。
对于第一种方式,由于没有考虑到利用体系结构的特性,所以会产生比较低性能的代码。例如,向量寄存器不够用时一般直接溢出到内存中,这远远慢于先溢出到标量寄存器中、再考虑是否溢出到内存。另外,发明人还发现,在编译过程中,当不同寄存器分开来进行分析处理,一般会选择进行多次的数据流分析以及生存区间或冲突图的建立,这会造成编译时间很慢。
第二种方式将各种寄存器一起混合分配,考虑了体系结构的特性,会比第一种方式在以上提及的情况时能产生更好的代码。但是,发明人发现,在有些时候,例如向量寄存器的资源不是特别紧张,或者在某些时刻不是特别紧张的情况下,这种方式仍仅考虑向量寄存器溢出到标量寄存器,而没有注意到标量寄存器溢出到向量寄存器也可能提高性能。当然,现有的算法框架也无法支持后一种溢出方式。这是因为,将向量寄存器和标量寄存器的分配混合,有可能一个标量寄存器溢出到向量寄存器的某一个域而导致后来某一个向量寄存器所有域被进一步溢出。因此,在标量寄存器溢出到向量寄存器时,无法知道该溢出到哪一个向量寄存器才是“安全的”。另外,发明人还发现,在编译时,这种方式会在分析过程中对原中间表示引入新的表达式,是一种动态的增量的修改过程,这一过程虽然比完全重建(第一种方式)要优越,但还是会显著地增加编译时间。另一方面,这种增量修改还会导致对分析结果的微调优化无法进行,因为这种方式是在分析过程中改动了中间表示,最终分配结果在分析结束后已经结束,不能对其进行调整。在这种情况下要想获得更高性能的分析结果,就对分配的主体算法的代价模型以及选择策略提出了更高的要求。然而,这样的要求往往又会进一步增加算法收敛时间,增加编译时间。
基于此,本申请提出一种建立虚拟寄存器生存区间的方法以及一种编译方法,能够减少寄存器分配的编译时间,提高编译生成代码的性能。
下面对根据本申请实施例的建立虚拟寄存器生存区间的方法及编译方法进行详细说明。
图2示出根据本申请示例实施例的建立虚拟寄存器生存区间的方法。根据本实施例的方法可用于在分配不同宽度寄存器时建立虚拟寄存器生存区间。
参见图2,在S201,获取源文件的中间表示。所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令。其中,所述第一类型虚拟寄存器为标量寄存器,第二类型虚拟寄存器为向量寄存器。
在S203,为所述指令按顺序建立递增或递减的程序点编号。
根据示例实施例,为作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令建立统一的程序点编号,从而以后可使用同一表示逻辑建立生存区间。根据示例实施例,例如,按中间表示中伪指令出现的顺序建立递增或递减的程序点编号,但本申请不限于此。
根据一些实施例,程序点编号可建立为n*m
例如,在下面的中间表示中,m取2,P取2,程序点编号为4(2的2次幂)的倍数。
(28)r1=1 (32)
(20)r2=2 (24)
(12)v2=f(r1,r2) (16)
(4)v1=v2+v1 (8)
r1和r2为第二类型虚拟寄存器(例如,虚拟标量寄存器),v2为第一类型虚拟寄存器(例如,虚拟向量寄存器),f为函数,表示左边是通过右边的两个虚拟寄存器计算生成的。
在S204,利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间。
根据一些实施例,在利用例如数据流分析获得第一和第二类型虚拟寄存器的生存信息之后,例如通过对源文件的中间表示进行一次扫描可容易地利用程序点编号表示第一和第二类型虚拟寄存器的生存区间。例如,假设IR里的指令按顺序(例如,IR中伪指令出现的顺序)编号,即程序点编号,通过对IR的程序点编号进行遍历,可得到变量v的生存区间[i,j],即:不存在编号为j1(j1>j)的指令,使得变量v在j1处活跃,且不存在编号为i1(i1
例如,在前面的例子中,r1在程序点编号32处将进入赋值1给r1,r1在程序点28处开始生存,在程序点编号16的下一程序点编号12处不再生存,因此r1的生存区间为[28,16]。类似地,r2的生存区间为[20,16],v2的生存区间为[12,8]。
这样,当例如标量寄存器需要溢出时,由于采用同一表示逻辑建立生存区间,可以容易地基于一致的生存区间表示,选择“安全的”向量寄存器来溢出,从而可充分地利用各种寄存器,有效提高代码性能,提高程序执行速度。
在S205,在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间,为所述第一类型溢出区间建立第一类型溢出点编号。
根据一些实施例,在进行第一类型寄存器和第二类型寄存器分配过程中,如果所述第一类型虚拟寄存器发生溢出,则在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器,为所述第一类型溢出区间建立第一类型溢出点编号。
例如,根据一些实施例,所述第一类型溢出点编号与在前相邻程序点编号相差m
例如,在下面的中间表示中,K取1,第一类型溢出点编号与在前相邻程序点编号相差2
(28)r1=1 (32)
(20)r2=2 (24)
(12)v2=f(r1,r2) (16)
(10)r3,r4=spill(v1) (10)
(4)v1=v2+v1 (8)
r3和r4为增加的第二类型虚拟寄存器(例如,虚拟标量寄存器),spill(v1)为第一类型溢出伪指令。
这样,根据示例实施例,在需要分析多种寄存器的分配时,不希望对每种寄存器都重新生成生存区间,所以采用类似于增量修改的策略。根据当前的分析结果,局部性的修改部分受影响的生存区间,而不是重新建立生存区间。当使用指数间隔的区间形式时,在模拟插入溢出代码时,不需要改变原来的生存区间。
例如,按照寄存器的分层分配算法,第一层分配时发现向量寄存器不够用,将其溢出到标量寄存器(实际操作中并不在当前阶段插入spill这条伪指令,而是象征性地插入用于r3、r4的溢出区间,与r1、r2的生存区间一起进入第二层的标量寄存器分配)。由于每两个程序点相差4,认为spill这条指令插在了类似于10这种是2的倍数但不是4的倍数的程序点上。可以看到,产生这样的生存区间不会改变类似于r1、r2这些原有的生存区间,因为已经“预留”具有特定属性的位置。
根据示例实施例,向量寄存器溢出到标量寄存器所产生的新的虚拟标量寄存器的生存区间无需进一步计算,可以通过原向量寄存器生存周期直接得到(例如,等于原虚拟向量寄存器的生存区间;或者原虚拟向量寄存器溢出区间与相邻程序点的集合等,本领域技术人员可根据实际情况和具体算法进行调整或优化),从而对于向量寄存器溢出到标量寄存器这种模式可以采用与原来标量寄存器相同的处理模式。
在S207,在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间,为所述第二类型溢出区间建立第二类型溢出点编号。
根据一些实施例,在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间以用于增加第二类型溢出伪指令,为所述第二类型溢出区间建立第二类型溢出点编号,所述第二类型溢出点编号与在前相邻程序点编号或第一类型溢出点编号相差m
例如,在下面的中间表示中,Q取0,第二类型溢出点编号与在前相邻第一类型溢出点编号相差2
(28)r1=1 (32)
(20)r2=2 (24)
(12)v2=f(r1,r2) (16)
(10)r3,r4=spill(v1) (10)
(9)ram3,ram4=spill(r3,r4) (9)
(4)v1=v2+v1 (8)
r3和r4为增加的第二类型虚拟寄存器(例如,虚拟标量寄存器),spill(r3,r4)为第二类型溢出伪指令。
在示例中,按照寄存器的分层分配算法,第二层分配标量寄存器时,每一行(包括溢出行)都看成原始代码(当然,实际上第一层分配时spill没有真正插入,这里只是把所有能被2整除但不能被4整除的程序点对应的生存区间除了分析过了的以外都当作真实的标量区间进行寄存器分配分析),在“溢出”时也没有实际插代码,而只是产生了标量寄存器的溢出区间。
根据以上描述的本申请实施例,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关。例如,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号根据相应程序点出现的位置顺序编号。所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。例如,将程序点表示为4的倍数,向量寄存器溢出点为2的倍数但却不是4的倍数,标量寄存器溢出点为奇数。这样,为中间表示中的指令按顺序建立递增或递减的程序点编号,可以兼容不同种类(宽度)的寄存器,使得变量的生存区间的整个建立过程可用同一表示逻辑。
根据以上描述的本申请一些实施例,为中间表示中的指令统一建立递增或递减的程序点编号,例如,将程序点表示为4的倍数,向量寄存器溢出点为2的倍数但却不是4的倍数,标量寄存器溢出点为奇数,可以兼容不同种类的寄存器,使得变量的生存区间的整个建立过程可用同一表示逻辑。
根据示例实施例,在建立生存区间过程中,没有在溢出点插入存储、装载代码,故而可以在分析完成后进行微调和优化。
根据一些实施例,在寄存器分配过程中,如果第一类型虚拟寄存器发生溢出,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器之后,利用原第一类型虚拟寄存器的生存区间可直接获得所述增加的第二类型虚拟寄存器的生存区间。因此,不需要额外分析就能给出溢出产生的标量的区间。例如,向量寄存器溢出到标量寄存器所产生的新的虚拟标量寄存器的生存区间无需进一步计算,可以通过原向量寄存器生存周期直接得到,从而对于向量寄存器溢出到标量寄存器这种模式可以采用与原来标量寄存器相同的处理模式。
例如,对于增加的第二类型虚拟寄存器r3和r4,可以直接利用原第一类型虚拟寄存器v2的生存区间[12,8]确定r3和r4的生存区间例如为[12,8],也可以使用更精确的区间[10,8]。当然,也可以根据实际情况和具体算法进行调整或优化,此处不再赘述。
根据示例实施例,在进行第二类型寄存器分配时,也一并为所增加的第二类型虚拟寄存器的生存区间[12,8]分配第二类型寄存器。
在示例实施例中,标量寄存器溢出时产生标量寄存器的溢出区间。然后,可结合已分配结束的向量寄存器的生存区间进行分析,在不与已分配向量寄存器生存区间冲突的情况下,利用空闲的向量寄存器进行溢出,提高编译代码性能。如果不采用根据本申请兼容多种寄存器的生存区间统一表示逻辑,会需要再进行一遍代价很高的数据流分析来重新计算生存区间。
这样,根据示例实施例,向量寄存器和标量寄存器的分配不会混合,但可以共同使用一套生存区间表示逻辑。例如,作为区别,分析时,能被4整除的程序点为真实的程序点;能被2整除但不能被4整除的点为向量寄存器的虚拟程序点(虚拟向量寄存器溢出产生的溢出点);奇数程序点(例如,如前示例,能被2
根据示例实施例,将程序点编号融入通常使用的生存区间分析中,构成统一的生存区间表示方式,这种生存区间表示方式和分析流程结合,能减少编译时间,同时产生更高质量的目标代码。
图3示出根据本申请示例实施例的编译方法。该编译方法中可使用前述建立虚拟寄存器生存区间的方法。
如前面所描述的,在编译过程中,根据实际的计算体系结构,需要分配多种不同宽度的寄存器,例如第一类型寄存器和第二类型寄存器,第一类型寄存器的宽度大于第二类型寄存器的宽度。例如,第一类型寄存器可以是512位宽的向量寄存器,第二类型寄存器可以是48位宽的标量寄存器。
参见图3,参见图2,在S301,获取源文件的中间表示。所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令。
在S303,为所述指令按顺序建立递增或递减的程序点编号。参见前面参照图2对S203的说明,此处省略其详细描述。
在S305,利用所述程序点编号表示虚拟寄存器生存区间。根据示例实施例,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间。参见前面参照图2对S204的说明,此处省略其详细描述。
在S307,为所述第一类型虚拟寄存器的生存区间分配第一类型寄存器。
基于所建立的生存区间,可通过线性扫描算法分配第一类型寄存器。易于理解,这里,第一类型虚拟寄存器和第一类型寄存器对应同样的变量类型。
在S309,在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器,为所述第一类型溢出区间建立第一类型溢出点编号。参见前面参照图2对S205的说明,此处省略其详细描述。
在S311,为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器以及为所述增加的第二类型虚拟寄存器的生存区间分配第二类型寄存器。
与第一类型寄存器的分配类似,基于所建立的第二类型虚拟寄存器的生存区间,可通过例如线性扫描算法分配第二类型寄存器。易于理解,这里,第二类型虚拟寄存器和第二类型寄存器对应同样的变量类型。
如前所述,第一寄存器溢出到第二寄存器产生的增加的第二虚拟寄存器的生存区间无需进一步计算,可利用原第一类型虚拟寄存器的生存区间直接获得。因此,不需要多次的数据流分析等额外工作就能给出溢出产生的标量的区间。
根据一些实施例,在为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器时,如果所述第二类型虚拟寄存器发生溢出,首先选择可用的所述第一类型寄存器进行溢出;如果没有可用的所述第一类型寄存器,则溢出到栈空间。由于采用同一表示逻辑建立生存区间,当例如标量寄存器需要溢出时,可以容易地基于一致的生存区间表示。另外,不同寄存器的分配有一定的先后顺序,例如在分配完向量寄存器后,再进行标量寄存器的分配。因此,可以选择“安全的”向量寄存器来溢出,从而可充分地利用各种寄存器,有效提高代码性能,提高程序执行速度。换言之,通过复用第一类型寄存器而避免溢出到内存,例如栈空间,可以提高编译后代码的运行效率。
在S313,在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间以用于增加第二类型溢出伪指令,为所述第二类型溢出区间建立第二类型溢出点编号。参见前面参照图2对S207的说明,此处省略其详细描述。
根据以上描述的本申请实施例,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关。例如,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号根据相应程序点出现的位置顺序编号。所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。例如,将程序点表示为4的倍数,向量寄存器溢出点为2的倍数但却不是4的倍数,标量寄存器溢出点为奇数。这样,为中间表示中的指令统一建立递增或递减的程序点编号,可以兼容不同种类(宽度)的寄存器,使得变量的生存区间的整个建立过程可用同一表示逻辑。
根据示例实施例,在建立生存区间过程中,没有在溢出点插入存储、装载代码,故而可以在分析完成后进行微调和优化。
根据一些实施例,在寄存器分配过程中,如果第一类型虚拟寄存器发生溢出,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器之后,利用原第一类型虚拟寄存器的生存区间可直接获得所述增加的第二类型虚拟寄存器的生存区间。因此,不需要额外分析就能给出溢出产生的标量的区间。
例如,对于增加的第二类型虚拟寄存器r3和r4,可以直接利用原第一类型虚拟寄存器v2的生存区间[12,8]确定r3和r4的生存区间例如为[12,8]。当然,也可以根据实际情况和具体算法进行调整或优化,此处不再赘述。
根据示例实施例,在进行第二类型寄存器分配时,也一并为所增加的第二类型虚拟寄存器的生存区间[12,8]分配第二类型寄存器。
在示例实施例中,标量寄存器溢出时产生标量寄存器的溢出区间。然后,可结合已分配结束的向量寄存器的生存区间进行分析,在不与已分配向量寄存器生存区间冲突的情况下,利用空闲的向量寄存器进行溢出,提高编译代码性能。如果不采用根据本申请兼容多种寄存器的生存区间统一表示逻辑,会需要再进行一遍代价很高的数据流分析来重新计算生存区间。
这样,根据示例实施例,向量寄存器和标量寄存器的分配不会混合,但可以共同使用一套生存区间表示逻辑。例如,作为区别,分析时,能被4整除的程序点为真实的程序点;能被2整除但不能被4整除的点为向量寄存器的虚拟程序点(虚拟向量寄存器溢出产生的溢出点);奇数程序点(例如,如前示例,能被2
根据示例实施例,将程序点编号融入通常使用的生存区间分析中,构成统一的生存区间表示方式,这种生存区间表示方式和分析流程结合,能减少编译时间,同时产生更高质量的目标代码。
根据一些实施例,前述编译方法还可包括括基于所述分配结果和优化后的代码进行代码重写,包括重写寄存器及插入溢出代码等。例如,根据所述第一类型寄存器和所述第二类型寄存器的分配结果,重写对应的第一类型虚拟寄存器和第二类型虚拟寄存器。另外,代码重写还可包括在第一类型溢出点和第二类型溢出点插入相应溢出代码等。本领域技术人员对寄存器重写和插入溢出代码应已熟知,此处不再赘述。
图4示出根据本申请示例实施例的分配寄存器的方法。根据本实施例的方法可用于不同宽度寄存器的分配,例如用于分配向量寄存器和标量寄存器。根据本实施例的方法可用于在源程序编译过程中进行寄存器分配。
参见图4,在S401,根据本申请示例实施例的分配寄存器的方法包括基于第一类型虚拟寄存器的生存区间,进行第一类型寄存器的分配。
如前所述,根据示例实施例,利用例如数据流分析获得第一类型虚拟寄存器的存活信息,即在给定的程序点,哪些变量是“存活”的。存活信息给出了生存区间的线索。然后,通过对源文件的中间表示进行一次扫描可容易地建立第一类型虚拟寄存器的生存区间。基于所建立的生存区间,可通过例如线性扫描算法分配第一类型寄存器。易于理解,这里,第一类型虚拟寄存器和第一类型寄存器对应同样的变量类型。
参见图4,在S403,在所述第一类型寄存器的分配完成之后,基于所述第一类型虚拟寄存器的生存区间和第二类型虚拟寄存器的生存区间,进行第二类型寄存器的分配。
如前所述,所述第一类型虚拟寄存器的生存区间和所述第二类型虚拟寄存器的生存区间可使用同一表示逻辑,通过对中间表示的一次扫描得到,从而可以减少寄存器分配时间。
与第一类型寄存器的分配类似,基于所建立的第二类型虚拟寄存器的生存区间,可通过例如线性扫描算法分配第二类型寄存器。
参见图4,在S405,判断第二类型虚拟寄存器是否发生溢出。如果发生溢出,则转到S407;否则,可进行后续其他处理,例如进行其他寄存器分配或基于寄存器分配结果进行代码优化处理等。
参见图4,在S407,在进行第二类型寄存器的分配时,如果所述第二类型虚拟寄存器发生溢出,首先选择可用的所述第一类型寄存器进行溢出。这样,通过复用第一类型寄存器而避免溢出到内存,例如栈空间,可以提高编译后代码的运行效率。
根据本实施例,不同寄存器的分配有一定的独立性,这样可以使同一套核心算法应用于不同的寄存器。同时,不同寄存器的分配有一定的先后顺序,例如在分配完向量寄存器后,再进行标量寄存器的分配,这样可以获取向量寄存器的分配结果。当标量寄存器需要溢出时,选择安全的策略,例如在不引起向量寄存器的溢出的情况下选择一个向量寄存器来溢出标量寄存器。这样,由于充分地利用了各种寄存器,可以有效提高代码性能,提高程序执行速度。
图5示出根据本申请另一示例实施例的分配寄存器的方法。
图5所示的方法与图4所示方法基本类似,区别在于图5还示出第一类型寄存器发生溢出的情况以及第二类型寄存器溢出到栈空间的情况。因此,这里将省略相同或相似步骤的详细描述。
参见图5,在S501,基于第一类型虚拟寄存器的生存区间,进行第一类型寄存器的分配。
在S502A,如果所述第一类型寄存器发生溢出,则转到S502B;否则,转到S503。
在S502B,溢出到第二类型寄存器。
在S503,在所述第一类型寄存器的分配完成之后,基于所述第一类型虚拟寄存器的生存区间和第二类型虚拟寄存器的生存区间,进行第二类型寄存器的分配。
在S505,判断第二类型虚拟寄存器是否发生溢出。如果发生溢出,则转到S506;否则,可进行后续其他处理,例如进行其他寄存器分配或基于寄存器分配结果进行代码优化处理等。
在S506,判断是否存在可用的第一类型寄存器。如果存在可用的第一类型寄存器,则转到S507;否则转到S509。
在S507,选择可用的所述第一类型寄存器进行溢出。这样,通过复用第一类型寄存器而避免溢出到内存,例如栈空间,可以提高编译后代码的运行效率。
在S509,不存在可用的第一类型寄存器时,溢出到栈空间。
根据该实施例,一旦发生溢出行为,向量寄存器会先行溢出到标量寄存器,而标量寄存器则会在没有可用的向量寄存器的情况下才溢出到栈上。这样,向量寄存器会先行溢出到标量寄存器而不是直接溢出到内存,可以提高代码的执行效率。
上面主要从方法的角度对本申请实施例进行了介绍。本领域技术人员应该很容易意识到,结合本文中所公开的实施例所描述的各示例的操作或步骤,本申请能够以硬件或硬件和计算机软件的结合形式来实现。本领域技术人员可以对每个特定的操作或方法使用不同方式来实现所描述的功能,这种实现不应认为超出本申请的范围。
下面描述本申请的装置实施例。对于本申请装置实施例中未披露的细节,可参照本申请方法实施例。
图6示出根据本申请示例实施例的建立虚拟寄存器生存区间的装置。该装置可用于执行上述建立虚拟寄存器生存区间的方法。
如图6所示,根据示例实施例的寄存器分配装置600包括中间表示模块601、程序点模块603、第一生存区间模块604、第一溢出模块605、第二溢出模块607。
参见图6并参照前面的描述,中间表示模块601用于获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令。
程序点模块603用于为所述指令按顺序建立递增或递减的程序点编号。
第一生存区间模块604用于利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间。
第一溢出模块605用于在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间,为所述第一类型溢出区间建立第一类型溢出点编号。
第二溢出模块607用于在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间,为所述第二类型溢出区间建立第二类型溢出点编号。
根据示例实施例,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。
根据该实施例的寄存器分配装置可执行与前面提供的方法类似的功能,其他功能可参见前面的描述,此处不再赘述。
图7示出根据本申请示例实施例的编译装置。该装置可用于执行上述编译方法。
如图7所示,根据示例实施例的编译装置700包括中间表示模块701、程序点模块703、第一生存区间模块705、第一分配模块707、第一溢出模块709、第二分配模块713及第二溢出模块715。
参见图7并参照前面的描述,中间表示模块701用于获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令。
程序点模块703用于为所述指令按顺序建立递增或递减的程序点编号。
第一生存区间模块705用于利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间。
第一分配模块707用于为所述第一类型虚拟寄存器的生存区间分配第一类型寄存器。
第一溢出模块709用于在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器,为所述第一类型溢出区间建立第一类型溢出点编号。
第二分配模块713用于为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器以及为所述增加的第二类型虚拟寄存器的生存区间分配第二类型寄存器,所述第一类型寄存器的宽度大于所述第二类型寄存器的宽度。
第二溢出模块715用于在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间以用于增加第二类型溢出伪指令,为所述第二类型溢出区间建立第二类型溢出点编号。
根据示例实施例,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。
根据该实施例的编译装置可执行与前面提供的方法类似的功能,其他功能可参见前面的描述,此处不再赘述。
图8示出根据本申请示例实施例的电子设备的框图。
下面参照图8来描述根据本申请的这种实施方式的电子设备200。图8显示的电子设备200仅仅是一个示例,不应对本申请实施例的功能和使用范围带来任何限制。
如图8所示,电子设备200以通用计算设备的形式表现。电子设备200的组件可以包括但不限于:至少一个处理单元210、至少一个存储单元220、连接不同系统组件(包括存储单元220和处理单元210)的总线230、显示单元240等。
存储单元220存储有程序代码,程序代码可以被处理单元210执行,使得处理单元210执行本说明书描述的根据本申请各实施例的方法。
存储单元220可以包括易失性存储单元形式的可读介质,例如随机存取存储单元(RAM)2201和/或高速缓存存储单元2202,还可以进一步包括只读存储单元(ROM)2203。
存储单元220还可以包括具有一组(至少一个)程序模块2205的程序/实用工具2204,这样的程序模块2205包括但不限于:操作系统、一个或者多个应用程序、其它程序模块以及程序数据,这些示例中的每一个或某种组合中可能包括网络环境的实现。
总线230可以为表示几类总线结构中的一种或多种,包括存储单元总线或者存储单元控制器、外围总线、图形加速端口、处理单元或者使用多种总线结构中的任意总线结构的局域总线。
电子设备200也可以与一个或多个外部设备300(例如键盘、指向设备、蓝牙设备等)通信,还可与一个或者多个使得用户能与该电子设备200交互的设备通信,和/或与使得该电子设备200能与一个或多个其它计算设备进行通信的任何设备(例如路由器、调制解调器等等)通信。这种通信可以通过输入/输出(I/O)接口250进行。并且,电子设备200还可以通过网络适配器260与一个或者多个网络(例如局域网(LAN),广域网(WAN)和/或公共网络,例如因特网)通信。网络适配器260可以通过总线230与电子设备200的其它模块通信。应当明白,尽管图中未示出,可以结合电子设备200使用其它硬件和/或软件模块,包括但不限于:微代码、设备驱动器、冗余处理单元、外部磁盘驱动阵列、RAID系统、磁带驱动器以及数据备份存储系统等。
本申请还提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现上述方法的步骤。
本申请实施例还提供一种计算机程序产品,该计算机程序可操作来使计算机执行如上述方法实施例中记载的部分或全部步骤。
本领域的技术人员可以清楚地了解到本申请的技术方案可借助软件和/或硬件来实现。本说明书中的“单元”和“模块”是指能够独立完成或与其他部件配合完成特定功能的软件和/或硬件,其中硬件例如可以是现场可编程门阵列(Field-ProgrammaBLE GateArray,FPGA)、集成电路(Integrated Circuit,IC)等。
需要说明的是,对于前述的各方法实施例,为了简单描述,故将其都表述为一系列的动作组合,但是本领域技术人员应该知悉,本申请并不受所描述的动作顺序的限制,因为依据本申请,某些步骤可以采用其他顺序或者同时进行。
在上述实施例中,对各个实施例的描述都各有侧重,某个实施例中没有详述的部分,可以参见其他实施例的相关描述。
以上对本申请实施例进行了详细描述和解释。应清楚地理解,本申请描述了如何形成和使用特定示例,但本申请不限于这些示例的任何细节。相反,基于本申请公开的内容的教导,这些原理能够应用于许多其它实施例。
通过对示例实施例的描述,本领域技术人员易于理解,根据本申请实施例的寄存器分配方法和编译方法至少具有以下优点中的一个或多个。
根据一些实施例,通过减少不必要的数据流分析并且避免引入过于复杂的依赖关系(复杂的依赖关系甚至可能导致无法收敛),可以减少编译时间。
根据一些实施例,通过不同寄存器之间适当的相互溢出,可以提高编译生成代码的性能。
根据一些实施例,为中间表示中的指令建立递增或递减的程序点编号,可以兼容不同种类的寄存器,使得变量的生存区间的整个建立过程可用同一表示逻辑。
根据一些实施例,在建立生存区间过程中,没有在溢出点插入存储、装载代码,而是代之以溢出伪指令,故而可以在分析完成后进行微调和优化。
根据一些实施例,如果第一类型虚拟寄存器发生溢出,在相应的第一类型溢出点增加溢出第一伪指令和第二类型虚拟寄存器之后,利用原第一类型虚拟寄存器的生存区间直接获得所述增加的第二类型虚拟寄存器的生存区间,从而可提高编译效率。
根据一些实施例,向量寄存器溢出到标量寄存器所产生的新的虚拟标量寄存器的生存区间无需进一步计算,可以通过原向量寄存器生存周期直接得到,从而对于向量寄存器溢出到标量寄存器这种模式可以采用与原来标量寄存器相同的处理模式。标量寄存器溢出时也可以产生类似区间,从而结合已分配结束的向量寄存器的生存区间进行分析,在不与已分配向量寄存器生存区间冲突的情况下,利用空闲的向量寄存器进行溢出。如果不采用根据本申请兼容多种寄存器的生存区间统一表示逻辑,会需要再进行一遍代价很高的数据流分析来重新计算生存区间。
根据一些实施例,向量寄存器和标量寄存器的分配不会混合,但可以共同使用一套生存区间表示逻辑。这样,通过特定表示的溢出点,可以记录溢出代码的插入位置。
根据示例实施例,将程序点编号融入通常使用的生存区间分析中,构成统一的生存区间表示方式,这种生存区间表示方式和分析流程结合,能减少编译时间,同时产生更高质量的目标代码。
根据本申请实施例,不同寄存器的分配有一定的独立性,这样可以使同一套核心算法应用于不同的寄存器。同时,不同寄存器的分配有一定的先后顺序,即分层分配,例如在分配完向量寄存器后,再进行标量寄存器的分配,这样可以获取向量寄存器的分配结果。当标量寄存器需要溢出时,选择安全的策略,例如在不引起向量寄存器的溢出的情况下选择一个向量寄存器来溢出标量寄存器。这样,由于充分地利用了各种寄存器,可以有效提高代码性能,提高程序执行速度。
依据以下条款可更好地理解前述内容:
条款1、一种建立虚拟寄存器生存区间的方法,其特征在于,所述方法包括:
获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令;
为所述指令按顺序建立递增或递减的程序点编号;
利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间;
在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间,并为所述第一类型溢出区间建立第一类型溢出点编号;
在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间,并为所述第二类型溢出区间建立第二类型溢出点编号,
其中,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。
条款2、根据如条款1所述的方法,其特征在于,所述程序点编号为n*m
条款3、根据条款2所述的方法,其特征在于,所述第一类型溢出点编号与在前相邻程序点编号相差m
条款4、根据条款3所述的方法,其特征在于,所述第二类型溢出点编号与在前相邻程序点编号或第一类型溢出点编号相差m
条款5、一种用于编译的方法,其特征在于,所述方法包括:
获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令;
为所述指令按顺序建立递增或递减的程序点编号;
利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间;
为所述第一类型虚拟寄存器的生存区间分配第一类型寄存器;
在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器,为所述第一类型溢出区间建立第一类型溢出点编号;
为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器以及为所述增加的第二类型虚拟寄存器的生存区间分配第二类型寄存器;
在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间以用于增加第二类型溢出伪指令,为所述第二类型溢出区间建立第二类型溢出点编号,
其中,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容,且
其中,所述第一类型寄存器的宽度大于所述第二类型寄存器的宽度。
条款6、根据条款5所述的方法,其特征在于,所述程序点编号为n*mP,n为程序点的序号,m和P为大于1的预定自然数。
条款7、根据条款6所述的方法,其特征在于,所述第一类型溢出点编号与在前相邻程序点编号相差mK,K为小于P的预定整数。
条款8、根据条款7所述的方法,其特征在于,所述第二类型溢出点编号与在前相邻程序点编号或第一类型溢出点编号相差mQ,Q为小于K的预定整数。
条款9、根据条款5所述的方法,其特征在于,在为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器时,如果所述第二类型虚拟寄存器发生溢出,首先选择可用的所述第一类型寄存器进行溢出;如果没有可用的所述第一类型寄存器,则溢出到栈空间。
条款10、根据条款9所述的方法,其特征在于,还包括:
基于第一类型寄存器和第二类型寄存器的分配结果进行代码优化;
基于所述分配结果和优化后的代码进行代码重写。
条款11、根据条款10所述的方法,其特征在于,所述基于所述分配结果和优化后的代码进行代码重写,包括:
根据所述第一类型寄存器和所述第二类型寄存器的分配结果,重写对应的第一类型虚拟寄存器和第二类型虚拟寄存器;以及
在所述第一类型溢出点和所述第二类型溢出点插入相应溢出代码。
条款12、一种建立虚拟寄存器生存区间的装置,其特征在于,所述装置包括:
中间表示模块,用于获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令;
程序点模块,用于为所述指令按顺序建立递增或递减的程序点编号;
第一生存区间模块,用于利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间;
第一溢出模块,用于在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间,为所述第一类型溢出区间建立第一类型溢出点编号;
第二溢出模块,用于在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间,为所述第二类型溢出区间建立第二类型溢出点编号,
其中,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。
条款13、一种编译装置,其特征在于,所述编译装置包括:
中间表示模块,用于获取源文件的中间表示,所述中间表示包括第一类型虚拟寄存器、第二类型虚拟寄存器以及作用于所述第一类型虚拟寄存器和所述第二类型虚拟寄存器的指令;
程序点模块,用于为所述指令按顺序建立递增或递减的程序点编号;
第一生存区间模块,用于利用所述程序点编号表示虚拟寄存器生存区间,所述虚拟寄存器生存区间包括所述第一类型虚拟寄存器的生存区间及所述第二类型虚拟寄存器的生存区间;
第一分配模块,用于为所述第一类型虚拟寄存器的生存区间分配第一类型寄存器;
第一溢出模块,用于在所述第一类型虚拟寄存器发生溢出时,在相应的第一类型溢出点插入第一类型溢出区间以用于增加第一类型溢出伪指令和第二类型虚拟寄存器,为所述第一类型溢出区间建立第一类型溢出点编号;
第二分配模块,用于为所述第二类型虚拟寄存器的生存区间分配第二类型寄存器以及为所述增加的第二类型虚拟寄存器的生存区间分配第二类型寄存器,所述第一类型寄存器的宽度大于所述第二类型寄存器的宽度;
第二溢出模块,用于在所述第二类型虚拟寄存器溢出时,在相应的第二类型溢出点插入第二类型溢出区间以用于增加第二类型溢出伪指令,为所述第二类型溢出区间建立第二类型溢出点编号,
其中,所述程序点编号、所述第一类型溢出点编号、所述第二类型溢出点编号与相应程序点的位置相关,所述程序点编号具有第一属性,所述第一类型溢出点编号具有第二属性,所述第二类型溢出点编号具有第三属性,所述第一属性、所述第二属性和所述第三属性彼此不相容。
条款14、一种电子设备,其特征在于,所述电子设备包括:
一个或多个处理器;
存储装置,用于存储一个或多个程序;
当所述一个或多个程序被所述一个或多个处理器执行,使得所述一个或多个处理器实现根据条款1-11中任一所述的方法。
条款15、一种计算机可读介质,其特征在于,所述计算机可读介质上存储有计算机程序,所述程序被处理器执行时实现根据条款1-11中任一所述的方法。
以上具体地示出和描述了本申请的示例性实施例。应可理解的是,本申请不限于这里描述的详细结构、设置方式或实现方法;相反,本申请意图涵盖包含在所附权利要求的精神和范围内的各种修改和等效设置。
- 建立虚拟寄存器生存区间的方法和装置及编译方法和装置
- 反编译过程中的寄存器传播方法、装置及反编译器