本发明涉及计算机技术,尤其涉及一种函数的访存优化编译方法和装置。
背景技术:
高级语言程序中存在大量函数调用,函数的序和跋是实现函数调用不可缺少的代码片段。函数序(Prologue)要负责建立栈空间,并将需要保存的寄存器保存在该栈空间中,函数跋(Epilogue)要负责从栈空间中恢复上述被保存的寄存器并销毁栈空间。有研究表明,在MIPS指令集下编译的若干典型程序中,函数序或函数跋部分的指令数占据了动态指令总数的约4%~25%,而函数序或函数跋中的大部分指令都是用于保存和恢复寄存器是标量访存指令(该标量访存指令在单条机器指令中可以对一个寄存器中的数据进行加载或存储)。因此,对函数序或函数跋中与寄存器保存和恢复相关的指令进行编译优化非常必要。
为了优化函数序或函数跋中与寄存器保存和恢复相关的指令,现有技术采用将多个访存宽度较小的标量访存指令合并成一个访存宽度较大的标量访存指令,从而可以减少函数序/跋中用于保存和恢复寄存器的标量访存指令的数量。
但是,现有技术虽然减少了函数序或函数跋中用于保存和恢复寄存器的标量访存指令的数量,但是其增加了函数序或函数跋中位运算指令的数量,因此,函数序或函数跋中的指令总数减少的效果并不理想;并且,现有技术中,将数据从源寄存器存储至内存或者从内存中将数据加载至目标寄存器的效率不高。
技术实现要素:
本发明提供一种函数的访存优化编译方法和装置,用以解决现有技术中函数序或函数跋中的指令总数减少的效果不理想,且将数据从源寄存器存储 至内存的存储效率或者从内存中将数据加载至目标寄存器的加载效率不高的技术问题。
第一方面,本发明提供一种函数的访存优化编译方法,包括:
编译器根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取至少一个寄存器分组;其中,每个所述寄存器分组中包括至少一个寄存器;
所述编译器根据每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型;
若所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则所述编译器对所述寄存器分组生成一条向量形式的第一中间代码;
所述编译器根据所述第一中间代码生成第一汇编代码,并将所述第一汇编代码输出给所述目标处理器。
结合第一方面,在第一方面的第一种可能的实施方式中,所述编译器根据每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型,具体包括:
所述编译器根据所述寄存器分组中的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,确定每个所述寄存器分组对应的中间代码的类型。
结合第一方面的第一种可能的实施方式,在第一方面的第二种可能的实施方式中,所述编译器根据所述寄存器分组中的寄存器的个数、所述向量访存指令的访存宽度、所述同一类型的寄存器的宽度,确定每个所述寄存器分组对应的中间代码的类型,具体包括:
所述编译器判断所述寄存器分组中的寄存器的个数是否等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若是,则所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码;
若否,则所述编译器根据所述寄存器分组的个数和所述向量访存指令的向下兼容结果,确定所述寄存器分组对应的中间代码的类型为标量形式的中 间代码,或,向量形式的中间代码。
结合第一方面至第一方面的第二种可能的实施方式中的任一项,在第一方面的第三种可能的实施方式中,所述编译器对所述寄存器分组生成一条向量形式的第一中间代码之后,所述方法还包括:
所述编译器为所述第一中间代码附加第一调试信息;所述第一调试信息用于指示所述寄存器分组中的寄存器被保存在栈中的位置。
结合第一方面的第三种可能的实施方式,在第一方面的第四种可能的实施方式中,所述编译器根据所述第一中间代码生成第一汇编代码,并将所述第一汇编代码输出给所述目标处理器,具体包括:
所述编译器根据所述第一调试信息生成第一调试伪指令;
所述编译器将所述第一调试伪指令和所述第一汇编代码输出给所述目标处理器。
结合第一方面,在第一方面的第五种可能的实施方式中,所述方法还包括:
若所述编译器确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码,则所述编译器对所述寄存器分组中的每个寄存器分别生成一条标量形式的第二中间代码;
所述编译器为所述第二中间代码附加第二调试信息;所述第二调试信息用于指示所述寄存器分组中的寄存器被保存在栈中的位置;
所述编译器根据所述第二中间代码生成第二汇编代码;
所述编译器根据所述第二调试信息生成第二调试伪指令;
所述编译器将所述第二调试伪指令和所述第二汇编代码输出给所述目标处理器。
结合第一方面的第三种可能的实施方式至第一方面的第五种可能的实施方式中任一项,在第一方面的第六种可能的实施方式中,所述待编译函数涉及的同一类型的寄存器的总个数为N,所述N为大于等于2的正整数;则所述编译器根据与所述函数的函数序或函数跋相关的同一类型的寄存器的宽度和所目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取寄存器分组,具体包括:
所述编译器对所述同一类型的寄存器按照从小到大的顺序进行编号;
所述编译器判断所述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于栈基址寄存器sp的第一偏移是否均为M字节对齐,获得第一判断结果;其中,所述M为所述向量访存指令的访存宽度;
所述编译器根据所述第一判断结果对所述同一类型的寄存器进行分组,获取所述寄存器分组。
结合第一方面的第六种可能的实施方式,在第一方面的第七种可能的实施方式中,所述编译器根据所述第一判断结果对所述同一类型的寄存器进行分组,获取所述寄存器分组,包括:
若所述第一判断结果为每个所述第一偏移均是M字节对齐,则所述编译器根据所述N、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组。
结合第一方面的第七种可能的实施方式,在第一方面的第八种可能的实施方式中,所述编译器根据所述N、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组,具体包括:
若所述第一判断结果为每个所述第一偏移均是M字节对齐,则所述编译器继续判断所述N是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若整除,则所述编译器对所述N个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器;
若不能整除,则所述编译器对前(N-P)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据后P个顺序编号的寄存器确定第二寄存器分组;其中,所述P为所述N除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
结合第一方面的第六种可能的实施方式,在第一方面的第九种可能的实施方式中,所述编译器根据所述第一判断结果对所述同一类型的寄存器进行 分组,获取所述寄存器分组,还包括:
若所述第一判断结果为至少一个所述第一偏移是M字节不对齐,则所述编译器确定不对齐的寄存器的个数,并根据所述N、所述不对齐的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,对所述同一类型的寄存器进行分组,获取所述寄存器分组。
结合第一方面的第九种可能的实施方式,在第一方面的第十种可能的实施方式中,所述编译器根据所述N、所述不对齐的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,对所述同一类型的寄存器进行分组,获取所述寄存器分组,具体包括:
若所述第一判断结果为至少一个所述第一偏移是M字节不对齐,则所述编译器确定第二偏移为所述第一个寄存器相对于所述栈基址寄存器sp的第一偏移加上不对齐的寄存器的个数T乘以所述不对齐的寄存器的宽度的乘积的和,并继续判断所述N减去所述T的差值是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若整除,则所述编译器对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器;
若不整除,则所述编译器对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组,并根据后Q个顺序编号的寄存器确定第三寄存器分组;其中,所述Q为所述(N-T)的差值除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
第二方面,本发明提供一种函数的访存优化编译装置,包括:
分组模块,用于根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取至少一个寄存器分组;其中,每个所述寄存器分组中包括至少一个寄存器;
确定模块,用于根据所述分组模块获得的每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型;
第一生成模块,用于在所述确定模块确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则对所述寄存器分组生成一条向量形式的第一中间代码;
第二生成模块,用于根据所述第一生成模块生成的所述第一中间代码生成第一汇编代码,并将所述第一汇编代码输出给所述目标处理器。
结合第二方面,在第二方面的第一种可能的实施方式中,所述确定模块,具体用于根据所述分组模块获得的所述寄存器分组中的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,确定每个所述寄存器分组对应的中间代码的类型。
结合第二方面的第一种可能的实施方式,在第二方面的第二种可能的实施方式中,所述确定模块,具体用于判断所述分组模块获得的所述寄存器分组中的寄存器的个数是否等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,若是,则确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码;若否,则根据所述寄存器分组的个数和所述向量访存指令的向下兼容结果,确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码,或,向量形式的中间代码。
结合第二方面至第二方面的第二种可能的实施方式中的任一项,在第二方面的第三种可能的实施方式中,所述装置还包括:
第一调试信息附加模块,用于在所述第一生成模块对所述寄存器分组生成一条向量形式的第一中间代码之后,为所述第一中间代码附加第一调试信息;所述第一调试信息用于指示所述寄存器分组中的寄存器被保存在栈中的位置。
结合第二方面的第三种可能的实施方式,在第二方面的第四种可能的实施方式中,所述第二生成模块,具体用于根据所述第一调试信息生成第一调试伪指令,并将所述第一调试伪指令和所述第一汇编代码输出给所述目标处理器。
结合第二方面,在第二方面的第五种可能的实施方式中,所述装置还包括:第二调试信息附加模块;其中,
所述第一生成模块,还用于在所述确定模块确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码时,对所述寄存器分组中的每个寄存器分别生成一条标量形式的第二中间代码;
所述第二调试信息附加模块,用于为所述第一生成模块生成的所述第二中间代码附加第二调试信息;所述第二调试信息用于指示所述寄存器分组中的寄存器被保存在栈中的位置;
所述第二生成模块,还用于根据所述第二中间代码生成第二汇编代码,并根据所述第二调试信息生成第二调试伪指令,并将所述第二调试伪指令和所述第二汇编代码输出给所述目标处理器。
结合第二方面的第三种可能的实施方式至第二方面的第五种可能的实施方式中的任一项,在第二方面的第六种可能的实施方式中,所述待编译函数涉及的同一类型的寄存器的总个数为N,所述N为大于等于2的正整数;则所述分组模块,具体包括:
排序单元,用于对所述同一类型的寄存器按照从小到大的顺序进行编号;
判断单元,用于判断所述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于栈基址寄存器sp的第一偏移是否均为M字节对齐,获得第一判断结果;其中,所述M为所述向量访存指令的访存宽度;
分组单元,用于根据所述判断单元的所述第一判断结果对所述同一类型的寄存器进行分组,获取所述寄存器分组。
结合第二方面的第六种可能的实施方式,在第二方面的第七种可能的实施方式中,所述分组单元,具体用于在所述判断单元的所述第一判断结果为每个所述第一偏移均是M字节对齐时,根据所述N、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组。
结合第二方面的第七种可能的实施方式,在第二方面的第八种可能的实施方式中,所述分组单元,具体用于在所述判断单元的所述第一判断结果为每个所述第一偏移均是M字节对齐时,指示所述判断单元继续判断所述N是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若整除,则对所述N个顺序编号的寄存器进行分组,获得至少一个第一 寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器;
若不能整除,则对前(N-P)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据后P个顺序编号的寄存器确定第二寄存器分组;其中,所述P为所述N除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
结合第二方面的第六种可能的实施方式,在第二方面的第九种可能的实施方式中,所述分组单元,还用于在所述判断单元的所述第一判断结果为至少一个所述第一偏移是M字节不对齐时,确定不对齐的寄存器的个数,并根据所述N、所述不对齐的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,对所述同一类型的寄存器进行分组,获取所述寄存器分组。
结合第二方面的第九种可能的实施方式,在第二方面的第十种可能的实施方式中,所述分组单元,具体用于在所述判断单元的所述第一判断结果为至少一个所述第一偏移是M字节不对齐时,确定第二偏移为所述第一个寄存器相对于所述栈基址寄存器sp的第一偏移加上不对齐的寄存器的个数T乘以所述不对齐的寄存器的宽度的乘积的和,并继续指示所述判断单元判断所述N减去所述T的差值是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若整除,则对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器;
若不整除,则对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组,并根据后Q个顺序编号的寄存器确定第三寄存器分组;其中,所述Q为所述(N-T)的差值除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度 的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
本发明实施例提供的函数的访存优化编译方法和装置,编译器根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取寄存器分组,并根据每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型;若所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则所述编译器对所述寄存器分组生成一条向量形式的第一中间代码,并根据所述第一中间代码生成第一汇编代码后,输出给目标处理器。本发明实施例提供的方法,大大减少了函数序或函数跋中的指令数量,节省了存储指令的空间,同时提高了计算机的访存效率,并减少了寄存器的压力。
附图说明
图1为本发明提供的函数的访存优化编译方法实施例一的流程示意图;
图2为本发明提供的函数的访存优化编译方法实施例二的流程示意图;
图3为本发明提供的函数的访存优化编译方法实施例三的流程示意图;
图4为本发明提供的函数的访存优化编译方法实施例四的流程示意图;
图5为本发明提供的函数的访存优化编译方法实施例五的流程示意图;
图6为本发明提供的函数的访存优化编译方法实施例六的流程示意图;
图7为本发明提供的函数的访存优化编译方法实施例七的流程示意图;
图8为本发明提供的函数的访存优化编译装置实施例一的结构示意图;
图9为本发明提供的函数的访存优化编译装置实施例二的结构示意图;
图10为本发明提供的函数的访存优化编译装置实施例三的结构示意图;
图11为本发明提供的函数的访存优化编译装置实施例四的结构示意图。
具体实施方式
本发明实施例涉及的方法,适用于计算机将编译文件中的高级语言编译成汇编语言的过程。由于计算机内部的处理器只识别汇编语言,因此,需要编译器将高级语言转换为汇编语言。一般的,编译文件中包括一个或多个函 数(在高级语言中只有函数,不存在函数的序),因此在将高级语言转换成汇编语言时,就涉及到函数序和函数跋的生成过程,函数序中包括用于保存寄存器的标量访存指令,函数跋中包括用于恢复寄存器的标量访存指令,本发明实施例提供的方法就是对现有的函数序或函数跋生成过程进行的优化处理的过程。
一般的,函数会涉及一个或多个寄存器,因此生成函数序或函数跋的过程,实际上是针对与该函数的函数序或函数跋相关的寄存器生成相应的保存或恢复这些寄存器的标量访存指令的过程。但是,这些用于保存或恢复寄存器的标量访存指令占据了整个函数序或函数跋的代码片段中的大部分比例,因此,现有技术采用将多个访存宽度较小的标量访存指令合并成一个访存宽度较大的标量访存指令的方式,来减少函数序或函数跋中用于保存或恢复寄存器的标量访存指令的数量,以达到优化编译过程的目的。但是,现有技术虽然减少了函数序或函数跋中用于保存或恢复寄存器的标量访存指令的数量,但是其增加了函数序或函数跋中位运算指令的数量,因此,函数序或函数跋中的指令总数减少的效果并不理想;并且,现有技术中,合并后的标量访存指令仍然也只是对应一个源或者目标寄存器,因此,其访存效率并不高,例如:计算机要从寄存器取128个字节的数据存储到内存,假设合并后的标量访存指令的访存宽度为32个字节,则该合并后的标量访存指令只能从一个源寄存器中取32个字节的内容到内存,计算机就需要取4次,故存储效率并不高(从内存中加载数据到寄存器也是同样的道理,其加载效率也不高)。另外,现有技术合并后的标量访存指令的访存结果,需要保存在临时寄存器中,也增加了寄存器的压力。
本发明实施例提供的方法,旨在解决现有技术中函数序或函数跋中的指令总数减少的效果不理想、访存效率不高以及寄存器压力大的技术问题。
需要说明的是,本发明实施例所说的“保存寄存器”指的是将寄存器中的内容存储在内存中,本发明实施例所说的“恢复寄存器”指的是将内存中的内容加载至寄存器中,为方便描述,采用本领域技术人员所公知的“保存寄存器或恢复寄存器”的描述方式。
下面以具体地实施例对本发明的技术方案进行详细说明。下面这几个具体的实施例可以相互结合,对于相同或相似的概念或过程可能在某些实施例 不再赘述。
图1为本发明提供的函数的访存优化编译方法实施例一的流程示意图。本实施例涉及的是函数序或函数跋的生成过程,即本实施例涉及的是对与函数的函数序或函数跋相关的同一类型的寄存器进行分组,获得寄存器分组,并对每个寄存器分组生成相应类型的中间代码,并根据所生成的中间代码进一步生成第一汇编代码并输出的具体过程。本实施例通过向量访存指令具有多个源或目标寄存器的特点,解决现有技术访存效率不高、函数序或函数跋的指令总数优化不理想以及寄存器压力大的技术问题。如图1所示,该方法包括:
S101:编译器根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取至少一个寄存器分组;其中,每个所述寄存器分组中包括至少一个寄存器。
具体的,本实施例中涉及的“同一类型的寄存器”均指的是与函数序或函数跋相关的同一类型的寄存器。一个函数的函数序或函数跋中涉及的寄存器可以包括一个或多个定点寄存器,还可以包括一个或多个浮点寄存器,还可以包括一个或多个定点寄存器,和一个或多个浮点寄存器。编译器确定了函数涉及的寄存器的类型之后,获取该类型的寄存器的宽度和目标处理器中向量访存指令的访存宽度。需要说明的是,上述同一类型的寄存器中的每个寄存器的宽度是相等的,寄存器的宽度可以为理解为这个寄存器存储或加载的数据的字节数,向量访存指令的访存宽度可以理解为该向量访存指令可以存储或者加载的字节数。编译器在获得上述同一类型的寄存器的宽度以及目标处理器中向量访存指令的访存宽度之后,对该类型的寄存器进行分组,获取至少一个寄存器分组,所述寄存器分组中包括一个或多个寄存器。例如,假设该函数涉及的寄存器的个数为9个,8个是定点寄存器,1个是浮点寄存器,则编译器根据定点寄存器的宽度以及目标处理器中向量访存指令的访存宽度对8个定点寄存器进行分组,可选的,可以是两两分组分为4个寄存器分组,也可以是四四分组分为2个寄存器分组,还可以是八八分组分为一个寄存器分组,这取决于定点寄存器的宽度以及目标处理器中向量访存指令的访存宽度的值;同时编译器也将上述1个浮点寄存器作为一个寄存器分组。
S102:编译器根据每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型。
具体的,当上述编译器获取至少一个寄存器分组之后,根据每个寄存器分组中寄存器的个数确定该寄存器分组对应的中间代码的类型。可选的,编译器可以根据寄存器分组中寄存器的个数确定该寄存器分组对应的中间代码的类型,例如,当编译器确定寄存器分组中的寄存器额数为1个时,就可以确定该寄存器分组对应的中间代码类型为标量形式;编译器还可以根据存器分组中寄存器的个数以及其他的参数(例如结合上述向量访存指令的访存宽度等)确定该寄存器分组对应的中间代码的类型。可选的,当上述编译器获得的寄存器分组中的寄存器的个数均相等时,其对应的中间代码的类型也相同。可选的,当编译器确定寄存器分组中寄存器的个数满足第一预设条件时,则确定该寄存器分组对应的中间代码的类型为向量形式的中间代码,若不满足该第一预设条件,编译器确定该寄存器分组对应的中间代码的类型为标量形式的中间代码。可选的,该第一预设条件可以为编译器根据所述同一类型的寄存器的宽度和向量访存指令的访存宽度确定的一预设值,还可以为目标处理器根据所述同一类型的寄存器的宽度和向量访存指令的访存宽度确定的一预设值,并发送给编译器的。
S103:若所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则所述编译器对所述寄存器分组生成一条向量形式的第一中间代码。
具体的,当上述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码时,则编译器针对该寄存器分组生成一条向量形式的第一中间代码,也就是说,编译器针对任一个中间代码的类型为向量形式的寄存器分组中的多个寄存器只生成一条向量形式的第一中间代码。
S104:编译器根据所述第一中间代码生成第一汇编代码,并将所述第一汇编代码输出给所述目标处理器。
具体的,当上述编译器针对每个寄存器分组分别生成一条向量形式的中间代码后,将每条向量形式的第一中间代码生成向量形式的第一汇编代码,并将所生成的向量形式第一汇编代码输出给目标处理器,供目标处理器执行该第一汇编代码。需要说明的是,根据向量形式的第一中间代码生成第一汇 编代码的过程,可以参照现有技术的方案,本发明实施例在此不再赘述。
另外,由于编译文件中包括一个或多个函数,一个函数的函数序或函数跋中涉及一个或多个寄存器,因此,在生成函数序或函数跋时,需要对编译文件中每一个函数的函数序或函数跋中进行处理,直到所有函数的函数序和函数跋都处理完毕,编译器的执行过程结束。
如上述所说,本发明实施例中,若编译器确定寄存器分组对应的中间代码的类型为向量形式的中间代码,则编译器对所述寄存器分组生成一条向量形式的第一中间代码,即编译器针对任一个中间代码类型为向量形式的寄存器分组中的多个寄存器只生成一条向量形式的第一中间代码,其并没有在生成过程中增加位运算等其他指令,故本发明实施例提供的方法大大减少了函数序或函数跋中的指令数量,节省了计算机存储指令的空间;另外,所生成的向量形式的第一中间代码或者第一汇编代码(即向量访存指令),其具有多个源或者目标寄存器,因此可以大大提高计算机的访存效率,例如,现有技术中计算机要从寄存器取128个字节的数据存储到内存,假设合并后的标量访存指令的访存宽度为32个字节,则该合并后的标量访存指令只能从一个源寄存器中取32个字节的内容到内存,计算机就需要存储4次,但是,本发明实施例,即使向量访存指令的访存宽度为32个字节,但由于其可以将4个源寄存器中同时取32个字节的内容到内存,故计算机只需要存储1次即可(从内存加载数据到寄存器也是同样的道理),因此,本发明实施例提供的方法,提高了计算机的访存效率;进一步地,本发明实施例提供的方法,并不需要将向量访存指令的访存结果保存在临时寄存器中,因此减少了寄存器的压力。
本发明实施例提供的函数的访存优化编译方法,编译器根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取寄存器分组,并根据每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型;若所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则所述编译器对所述寄存器分组生成一条向量形式的第一中间代码,并根据所述第一中间代码生成第一汇编代码后,输出给目标处理器。本发明实施例提供的方法,大大减少了函数序或函数跋中的指令数量,节省了存储指令的空间,同时提高了计算机的访存效率,并减少了寄 存器的压力。
在上述实施例的基础上,进一步地,上述S102具体包括:编译器根据所述寄存器分组中的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,确定每个所述寄存器分组对应的中间代码的类型。
可选的,编译器可以根据向量访存指令的访存宽度和上述同一类型的寄存器的宽度确定一参数值,编译器可以根据该参数值和上述寄存器分组中寄存器的个数确定该寄存器分组对应的中间代码的类型。可选的,该参数值可以为向量访存指令的访存宽度除以上述同一类型的寄存器的宽度的商值,还可以为上述同一类型的寄存器的宽度除以向量访存指令的访存宽度的商值,还可以为根据向量访存指令和上述同一类型的寄存器的宽度确定的任一变形后的参数值,即只要该参数值能够作为上述寄存器分组中寄存器个数的一个参考阈值即可。
优选的,参见图2,图2为本发明提供的函数的访存优化编译方法实施例二的流程示意图。本实施例涉及的是编译器根据寄存器分组中寄存器的个数、上述向量访存指令的访存宽度和上述同一类型的寄存器的宽度,确定所述寄存器分组对应的中间代码的类型的具体过程。如图2所示,该方法包括:
S201:编译器判断所述寄存器分组中的寄存器的个数是否等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;若是,则执行S202,若否,则执行S203。
具体的,编译器在对函数涉及的寄存器进行分组时,依据的是向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,即判断寄存器分组中的寄存器的个数是否等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,根据所得到的判断结果确定寄存器分组对应的中间代码的类型。若编译器对所有的定点寄存器进行分组,则依据的是向量访存指令的访存宽度除以定点寄存器的宽度的商值,若编译器对所有的浮点寄存器进行分组,则依据的是向量访存指令的访存宽度除以浮点寄存器的宽度的商值,也就是说,当函数涉及的寄存器既包括定点寄存器,也包括浮点寄存器时,则寄存器分组既有定点寄存器分组,也有浮点寄存器分组。
S202:编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码。
S203:编译器根据所述寄存器分组的个数和所述向量访存指令的向下兼容结果,确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码,或,向量形式的中间代码。
具体的,当上述编译器确定寄存器分组中的个数不等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值时,编译器可以根据所划分的寄存器分组的寄存器的个数和所述向量访存指令的向下兼容结果,确定其对应的中间代码的类型。可选的,当寄存器分组中的寄存器个数为一个时,则确定其对应的中间代码的类型为标量形式的中间代码,当寄存器分组中的寄存器个数大于1个时,则可以确定其对应的中间代码类型为标量形式的中间代码,也可以确定其对应的中间代码类型为向量形式的中间代码,这主要依据寄存器分组中寄存器的个数与目标处理器的向量访存指令的访存宽度之间的向下兼容结果的关系。例如,假设上述同一类型的寄存器为35个,上述同一类型的寄存器的宽度为8个字节,向量访存指令的访存宽度为32个字节,则编译器对上述同一类型的寄存器进行四四分组,即当编译器确定部分寄存器分组中寄存器的个数是4(这些寄存器分组中寄存器的个数等于向量访存指令的宽度除以同一类型的寄存器的宽度的商值),剩余的最后3个寄存器,若编译器将这3个寄存器分别划分为三个寄存器分组,则这三个寄存器分组对应的中间代码均为标量形式;若编译器将其中2个寄存器划分为一个寄存器分组,将最后一个寄存器划分为一个寄存器分组,则根据向量访存指令向下兼容的特点(目标处理器的向量访存指令的访存宽度是32个字节,则生成一条访存宽度为16字节的向量访存指令也是可以兼容的),寄存器个数为2个的寄存器分组对应的中间代码就可以是向量形式的,也就是说2个寄存器也只对应一条向量形式的中间代码,同样可以减少函数序或函数跋中指令的数量。
图3为本发明提供的函数的访存优化编译方法实施例三的流程示意图。本实施例涉及的是生成函数序的具体过程。需要说明的是,函数跋的生成过程与函数序的生成过程类似,只需要去掉下述步骤中附加第一调试信息第二调试信息的过程,以及去掉根据第一调试信息生成第一调试伪指令、根据第二调试信息生成第二调试伪指令的过程即可。本发明实施例以生成函数序为 例进行具体介绍。如图3所示,该方法包括:
S301:编译器根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取至少一个寄存器分组;其中,每个所述寄存器分组中包括至少一个寄存器。
具体的,S301的具体过程可以参照上述S101的描述,在此不再赘述
S302:编译器判断所述寄存器分组中的寄存器的个数是否等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;若是,则所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码;若否,则所述编译器进一步根据所述寄存器分组的个数和所述向量访存指令的向下兼容结果,确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码,或,向量形式的中间代码。
具体的,S302的具体描述可以参照上述实施例二中S201至S203中的描述,在此不再赘述。
S303:若所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则所述编译器对所述寄存器分组生成一条向量形式的第一中间代码;若所述编译器确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码,则所述编译器对所述寄存器分组中的每个寄存器分别生成一条标量形式的第二中间代码。
具体的,编译器根据上述所确定的每个寄存器分组的类型对所获取的每个寄存器分组生成对应类型的中间代码。即,对上述对应的中间代码类型为向量形式的中间代码的寄存器分组生成一条向量形式的第一中间代码,对上述对应的中间代码类型为标量形式的中间代码的寄存器分组中的每个寄存器分别生成一条标量形式的第二中间代码。例如,继续按照上述实施例二中所举的例子,对于寄存器个数为4个的寄存器分组,其对应的中间代码的类型为向量形式,则编译器就针对该寄存器分组只生成一条向量形式的第一中间代码;对于寄存器个数为3个的寄存器分组,其对应的中间代码的类型为标量形式的中间代码,则编译器就针对该寄存器分组中的每个寄存器分别生成一条标量形式的第二中间代码;对于寄存器个数为2个的寄存器分组,其对应的中间代码的类型为向量形式的第一中间代码,则编译器就针对该寄存器 分组也只生成一条向量形式的第一中间代码(需要说明的是,寄存器个数为2的寄存器分组对应的向量形式的第一中间代码,与寄存器个数为4的寄存器分组对应的向量形式的第一中间代码是不同的,本发明实施例只是将所有向量形式的中间代码统称为第一中间代码);对于寄存器个数为1个的寄存器分组,其对应的中间代码的类型为标量形式的中间代码,则编译器就针对该寄存器分组生成一条标量形式的第二中间代码。
S304:编译器为所述向量形式的第一中间代码附加第一调试信息,并为所述标量形式的第二中间代码附加第二调试信息;所述第一调试信息和所述第二调试信息均用于指示所述寄存器分组中的寄存器被保存在栈中的位置。
具体的,编译器为第一中间代码附加第一调试信息,该第一调试信息可以使得研发人员获知该第一中间代码对应的寄存器分组中的寄存器存储在栈中的位置,从而可以帮助研发人员调试程序;同时,编译器为第二中间代码附加第二调试信息,该第二调试信息也可以使得研发人员获知该第二中间代码对应的寄存器分组中的寄存器存储在栈中的位置,从而也可以帮助研发人员调试程序。
S305:编译器根据所述第一中间代码生成第一汇编代码,根据所述第二中间代码生成第二汇编代码。
S306:编译器根据所述第一调试信息生成第一调试伪指令,并根据所述第二调试信息生成第二调试伪指令。
S307:编译器将所述第一调试伪指令和所述第一汇编代码输出给所述目标处理器,并将所述第二调试伪指令和所述第二汇编代码输出给目标处理器。
具体的,S305至S307的具体执行过程,可以参照现有技术的方案,在此不再赘述。
本发明实施例提供的函数的访存优化编译方法,编译器根据待编译函数涉及的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述函数涉及的同一类型的寄存器进行分组,获取寄存器分组,并根据每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型;若所述编译器确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则所述编译器对所述寄存器分组生成一条向量形式的第一中间代码,并根据第一中间代码生成第一汇编代码,并结合附加给第一中 间代码的第一调试信息生成的第一调试伪指令,将所述第一调试伪指令和所述第一回汇编代码一起输出给目标处理器。本发明实施例提供的方法,大大减少了函数序或函数跋中的指令数量,节省了存储指令的空间,同时提高了计算机的访存效率,并减少了寄存器的压力,进一步还可以为研发人员调试程序提供帮助。
图4为本发明提供的函数的访存优化编译方法实施例四的流程示意图。本实施例涉及的是编译器对函数涉及的寄存器进行分组的具体过程。在上述实施例的基础上,上述S301具体包括如下步骤:
S401:编译器对所述函数涉及的同一类型的寄存器按照从小到大的顺序进行编号。
具体的,一个函数的函数序或函数跋涉及一个或多个寄存器,这些寄存器可能类型全部相同,也可能一部分是定点寄存器,另一部分是浮点寄存器,因此,编译器需要对同一类型的寄存器按照从小到大的顺序进行编号,若该函数涉及的寄存器既包括定点寄存器,也包括浮点寄存器,则编译器定点类型的寄存器和浮点类型的寄存器分别按照从小到大的顺序进行独立编号。可选的,这里的从小到大的编号不限定于是阿拉伯数字的大小编号,只要对寄存器的编号能够体现出寄存器之间的顺序即可,另外,这里的编号应该是连续的。
S402:编译器判断所述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于栈基址寄存器sp的第一偏移是否为M字节对齐,获得第一判断结果;其中,所述M为所述向量访存指令的访存宽度;若所述第一判断结果为每个所述第一偏移均是M字节对齐,则执行S403,若所述第一判断结果为至少一个所述第一偏移是M字节不对齐,则执行S404。
具体的,编译器确定了函数中与函数序或函数跋相关的寄存器的类型后,对于同一类型下的每个寄存器相对于所述栈基址寄存器sp的第一偏移,分别判断每个寄存器对应的第一偏移是否与目标处理器的向量访存指令的访存宽度M对齐,并根据所得到的第一判断结果对上述同一类型的寄存器进行分组,获取寄存器分组,具体参见下述S403至S408的具体过程。
S403:编译器根据所述N、所述向量访存指令的访存宽度和所述同一类 型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组。
具体的,若编译器确定上述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于所述栈基址寄存器sp的每个所述第一偏移均为M字节对齐,则可选的,编译器可以根据向量访存指令的访存宽度和上述同一类型的寄存器的宽度确定一参数值,编译器可以根据该参数值和上述N对上述同一类型的寄存器进行分组。可选的,该参数值可以为向量访存指令的访存宽度除以上述同一类型的寄存器的宽度的商值,还可以为上述同一类型的寄存器的宽度除以向量访存指令的访存宽度的商值,还可以为根据向量访存指令和上述同一类型的寄存器的宽度确定的任一变形后的参数值,即只要该参数值能够作为上述N的一个参考阈值即可。
优选的,参见图5所示实施例五,上述S403具体可以为包括下述步骤;
S501:编译器继续判断所述N是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;若整除,则执行S502,若不能整除,则执行S503。
具体的,若编译器确定上述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于所述栈基址寄存器sp的每个所述第一偏移均为M字节对齐,则编译器判断所述N是否可以整除所述向量访存指令的访存宽度除以所述函数涉及的同一类型的寄存器的宽度的商值的过程,实际上是在判断针对上述顺序编号后的同一类型的寄存器进行分组后,得到的各个寄存器分组中的寄存器的个数是否全部相等的过程,也就是判断上述N是否刚好按照所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值进行平均划分。
S502:编译器对所述N个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器。
具体的,若上述编译器判断N可以整除所述向量访存指令的访存宽度除以所述函数涉及的同一类型的寄存器的宽度的商值,就说明编译器对上述顺序编号的同一类型的寄存器进行分组后,得到的所有寄存器分组中的寄存器的个数是相等的,即恰好将上述同一类型的寄存器平均分完。例如,假设上 述同一类型的寄存器为8个,经过顺序编号后为{REG1,REG2,REG3,REG4,REG5,REG6,REG7,REG8},若向量访存指令的访存宽度为16个字节,上述同一类型的寄存器的宽度为8个字节,则二者的商值为2,且这8个寄存器相对于栈基址寄存器的第一偏移均是16字节对齐,则编译器将可以将这8个寄存器进行两两分组,得到4个寄存器分组{G1,G2,G3,G4},每个寄存器分组中寄存器的个数是相等的,其中,G1包括REG1和REG2,G2包括REG3和REG4,G3包括REG5和REG6,G4包括REG7和REG8;另外,编译器在得到相应的寄存器分组后,还会附加函数序中需要保存的寄存器在栈空间中占据的连续地址空间的起始地址,也就是说,最后G1包括[REG1 REG2offset],G2包括[REG3 REG4,offset+16],G3包括[REG5 REG6 offset+32],G4包括[REG7 REG8 offset+48],其中,offset为上述顺序编号后的REG1在所述栈中的保存地址相对于所述栈基址寄存器sp的第一偏移,也是REG1保存在栈空间中占据的连续地址空间的起始地址;offset+16为上述顺序编号后的REG3在所述栈中的保存地址相对于所述栈基址寄存器sp的第一偏移,也是REG3保存在栈空间中占据的连续地址空间的起始地址;offset+32为上述顺序编号后的REG5在所述栈中的保存地址相对于所述栈基址寄存器sp的第一偏移,也是REG5保存在栈空间中占据的连续地址空间的起始地址;offset+48为上述顺序编号后的REG7在所述栈中的保存地址相对于所述栈基址寄存器sp的第一偏移,也是REG7保存在栈空间中占据的连续地址空间的起始地址。
S503:编译器对前(N-P)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据后P个顺序编号的寄存器确定第二寄存器分组;其中,所述P为所述N除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
具体的,若上述编译器判断N不能整除所述向量访存指令的访存宽度除以所述函数涉及的同一类型的寄存器的宽度的商值,就说明编译器对上述N个同一类型的寄存器进行分组后,得到的部分寄存器分组中的寄存器的个数是相等的。即,编译器通过N除以(上述向量访存指令的访存宽度除以所述函数涉及的同一类型的寄存器的宽度的商值)得到的商值为第一寄存器分组的个数,得到的余数P就为上述N中除去寄存器分组后剩余的寄存器的个数, 然后编译器根据余下的P个寄存器确定第二寄存器分组。由于上述确定的第一寄存器分组中寄存器的个数等于上述向量访存指令的访存宽度除以所述函数涉及的同一类型的寄存器的宽度的商值,因此其对应的中间代码的类型即为向量形式;可选的,编译器可以将余下的P个寄存器确定为P个第二寄存器分组,每个第二寄存器分组中只包括一个寄存器,则根据寄存器的个数和向量访存指令的向下兼容结果就确定这P个寄存器分组对应的中间代码的类型即为标量形式的中间代码;可选的,编译器还可以根据上述向量访存指令向下兼容的特点将余下的P个寄存器进行重新分组,使得从这P个寄存器中得到的部分第二寄存器分组对应的中间代码为向量形式的中间代码,另一部分第二寄存器分组对应的中间代码为标量形式的中间代码。
综上,图5所示的方法步骤就详细的描述了当编译器确定上述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于所述栈基址寄存器sp的每个所述第一偏移均为M字节对齐的场景下,编译器根据上述N、上述向量访存指令的访存宽度和上述同一类型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组的一种可能的实施方式。
S404:编译器确定不对齐的寄存器的个数,并根据所述N、所述不对齐的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,对所述同一类型的寄存器进行分组,获取所述寄存器分组。
具体的,若编译器确定上述第一判断结果为上述同一类型的寄存器中的一个或多个寄存器在所述栈中的保存地址相对于sp的第一偏移为M字节不对齐后,则编译器可以根据不对齐的寄存器的个数、上述向量访存指令的访存宽度和上述同一类型的寄存器的宽度确定一参数值,从而使得编译器可以根据上述不对齐的寄存器的个数、上述N和该参数值对上述同一类型的寄存器进行分组。可选的,该参数值可以为向量访存指令的访存宽度除以上述同一类型的寄存器的宽度的商值,还可以为上述同一类型的寄存器的宽度除以向量访存指令的访存宽度的商值,还可以为根据向量访存指令和上述同一类型的寄存器的宽度确定的任一变形后的参数值,即只要该参数值能够作为上述不对齐的寄存器的个数以及上述N的一个参考阈值即可。
优选的,参见图6所示的实施例六,上述S404具体可以为包括下述步骤;
S601:编译器确定第二偏移为所述第一个寄存器相对于所述栈基址寄存 器sp的第一偏移加上不对齐的寄存器的个数T乘以所述不对齐的寄存器的宽度的乘积的和,并继续判断所述N减去所述T的差值是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。若整除,则执行S602,若不能整除,则执行S603。
具体的,若编译器确定上述同一类型的寄存器中的一个或多个寄存器在所述栈中的保存地址相对于所述栈基址寄存器sp的第一偏移为M字节不对齐,则编译器确定不对齐的寄存器的个数,然后根据不对齐的寄存器的个数确定第二偏移,即确定该第二偏移等于第一个寄存器相对于所述栈基址寄存器sp的第一偏移加上不对齐的寄存器的个数T乘以所述不对齐的寄存器的宽度的乘积的和,该第二偏移主要是为了确保后(N-T)个寄存器相对于所述栈基址寄存器sp的第一偏移为M字节对齐。
然后,编译器从上述N中除去这些不对齐的寄存器,并判断(N-T)的差值是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,即判断剩余的N-T个寄存器是否可以按照所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值为单位平均划分。
S602:编译器对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器。
具体的,若编译器判断(N-T)的差值能够整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,就说明编译器对上述同一类型的寄存器进行分组后,得到的所有寄存器分组中的寄存器的个数是相等的,即恰好将上述同一类型的寄存器平均分完。例如,假设上述同一类型的寄存器为9个,经过顺序编号后为{REG1,REG2,REG3,REG4,REG5,REG6,REG7,REG8,REG9},若向量访存指令的访存宽度为16个字节,上述同一类型的寄存器的宽度为8个字节,则二者的商值为2;若假设REG1相对于栈基址不是M字节对齐,则编译器确定第二偏移为REG1相对于sp的第一偏移加上8,并且编译器从9个寄存器中除去REG1,将后8个寄存器进行两两分组,得到4个寄存器分组{G1,G2,G3,G4},每个寄存 器分组中寄存器的个数是相等的,其中,G1包括REG2和REG3,G2包括REG4和REG5,G3包括REG6和REG7,G4包括REG8和REG9;另外,编译器在得到相应的寄存器分组后,还会附加函数序中需要保存的寄存器在栈空间中占据的连续地址空间的起始地址,也就是说,最后G1包括[REG2 REG3 offsetnew],G2包括[REG4 REG5,offsetnew+16],G3包括[REG6 REG7 offsetnew+32],G4包括[REG8 REG9 offsetnew+48],offsetnew为上述顺序编号后的REG2在所述栈中的保存地址相对于所述栈基址寄存器sp的第二偏移,也是REG2保存在栈空间中占据的连续地址空间的起始地址;offsetnew+16为上述顺序编号后的REG4在所述栈中的保存地址相对于所述栈基址寄存器sp的第二偏移,也是REG4保存在栈空间中占据的连续地址空间的起始地址;offsetnew+32为上述顺序编号后的REG6在所述栈中的保存地址相对于所述栈基址寄存器sp的第二偏移,也是REG6保存在栈空间中占据的连续地址空间的起始地址;offsetnew+48为上述顺序编号后的REG8在所述栈中的保存地址相对于所述栈基址寄存器sp的第二偏移,也是REG8保存在栈空间中占据的连续地址空间的起始地址
S603:编译器对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组,并根据后Q个顺序编号的寄存器确定第三寄存器分组;其中,所述Q为所述(N-T)的差值除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
具体的,若上述编译器判断(N-T)不能整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,就说明编译器对后(N-T)个同一类型的寄存器进行分组后,得到的部分寄存器分组中的寄存器的个数是相等的。即,编译器通过上述(N-T)的差值除以(上述向量访存指令的访存宽度除以所述函数涉及的同一类型的寄存器的宽度的商值)得到的商值为第一寄存器分组的个数,得到的余数Q就为上述后(N-T)个寄存器中除去寄存器分组后剩余的寄存器的个数,然后编译器根据上述前T个顺序编号的寄存器确定第二寄存器分组,并根据后Q个顺序编号的寄存器确定第三寄存器分组。由于上述确定的第一寄存器分组中寄存器的个数等于上述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,因此其对应的中间代码的 类型即为向量形式;可选的,编译器可以根据前T个顺序编号的寄存器的个数和向量访存指令的向下兼容结果确定T个第二寄存器分组,每个第二寄存器分组中包括一个寄存器,则这T个寄存器分组对应的中间代码的类型即为标量形式的中间代码;可选的,编译器还可以根据上述向量访存指令向下兼容的特点将上述T个寄存器进行重新分组,使得从这T个寄存器中得到的部分第二寄存器分组对应的中间代码为向量形式的中间代码,另一部分第二寄存器分组对应的中间代码为标量形式的中间代码;可选的,编译器可以将余下的Q个寄存器确定为Q个第三寄存器分组,每个第三寄存器分组中只包括一个寄存器,则相应的这Q个第三寄存器分组对应的中间代码的类型即为标量形式的中间代码;可选的,编译器还可以根据上述向量访存指令向下兼容的特点将余下的Q个寄存器进行重新分组,使得从这Q个寄存器中得到的部分第三寄存器分组对应的中间代码为向量形式的中间代码,另一部分第三寄存器分组对应的中间代码为标量形式的中间代码。
综上,图6所示的方法步骤就详细的描述了当编译器确定上述同一类型的寄存器中的一个或多个寄存器在所述栈中的保存地址相对于所述栈基址寄存器sp的第一偏移为M字节不对齐的场景下,编译器根据上述N、上述向量访存指令的访存宽度和上述同一类型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组的一种可能的实施方式。
为了更好的理解本发明实施例对函数序或函数跋相关的寄存器进行分组,以生成相应的保存或恢复寄存器的向量形式的中间代码,从而减少函数序或函数跋中用于保存或恢复寄存器的标量形式的指令的具体过程,此处举一个实际的例子来说明:
以龙芯3A的处理器为例,该处理器的向量访存指令具有双目标寄存器(每个目标寄存器的宽度是8个字节),向量访存指令的访存宽度为16字节,栈基址寄存器sp是16字节对齐的。为了方便描述,此处假设与函数序或函数跋相关的寄存器均为定点寄存器,指令“loadq r1,r2,offset(rbase)”表示将内存中以16字节对齐的地址(rbase)+offset中连续的16字节数据加载到两个定点目标寄存器中,其中r1对应高地址,r2对应低地址,指令“storeq r1,r2,offset(rbase)”表示将两个定点源寄存器中的16字节数据存储到内存中以16字节对齐的地址(rbase)+offset中去,其中r1对应高 地址,r2对应低地址。函数序中需要保存寄存器采用上述“storeq r1,r2,offset(rbase)”指令,函数跋中需要恢复的寄存器采用上述“loadq r1,r2,offset(rbase)”指令。下述例子以生成函数序中用于保存寄存器的向量形式的中间代码为例,对于生成函数跋中用于恢复寄存器的向量形式的中间代码只需要去掉下述附加调试信息和生成调试伪指令的过程,以及将存储指令替换为加载指令即可,本发明实施例在此不再赘述。另外,需要说明的是,对某个函数的序处理时,需要依次处理所有类型的寄存器,直到所有类型的寄存器的保存指令都生成完毕为止。具体的,假设与函数序相关的需要保存的定点类型的寄存器为N个,则该例子包括如下步骤,参见图7所示的实施例七:
S701:编译器将该类型中所需保存的N个寄存器按照编号从小到大排列,得到顺序编号的寄存器序列。
具体的,该寄存器序列为
S702:编译器判断该类型的每个寄存器相对于栈基址寄存器sp的偏移是否是16字节对齐。若是,则执行S703,若否,则执行S706。
S703:编译器判断所述N是否可以整除上述向量访存指令的访存宽度除以该类型寄存器的宽度的商值(该商值为2),即判断上述N是否为偶数。若是,则执行S704,若否,则执行S705。
S704:若整除(即N为偶数),则编译器对将上述顺序编号的N个寄存器进行分组,得到第一寄存器分组,第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以该类型的寄存器的宽度的商值,即对上述N个顺序编号的寄存器进行两两分组,每个第一寄存器分组中寄存器的个数为2,并给每个第一寄存器分组附加函数序中需要保存的寄存器在栈空间中占据的连续地址空间的起始地址。之后,执行S709。
具体的,得到的第一寄存器分组为
S705:若不能整除(即N为奇数,余数为1),编译器对前(N-1)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并将最后一个顺序编号的寄存器REGN确定为第二寄存器分组。之后,执行S709。
具体的,得到的第一寄存器分组为
S706:若编译器判断该类型的寄存器中REG1相对于栈基址寄存器sp的第一偏移不是16字节对齐,编译器确定第二偏移为上述REG1相对于栈基址寄存器sp的第一偏移(offset)加上不对齐的寄存器的个数T乘以所述不对齐的寄存器的宽度的乘积的和,即确定第二偏移offsetnew=offset+8;并且,编译器继续判断(N-1)是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值(该商值为2),即判断N-1是否为偶数。若是,则执行S707,若否,则执行S708。
S707:若N-1为偶数,则对后(N-1)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,即将排列后的REG2至REGN进行分组,获得至少一个第一寄存器分组;即对上述REG2至REGN的寄存器进行两两分组,每个第一寄存器分组中寄存器的个数为2,剩下REG1作为第二寄存器分组。之后,执行S709。
具体的,得到的第一寄存器分组为
S708:若N-1为奇数,则对后(N-1)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,即对上述REG2至REGN-1的寄存器进行两两分组,每个第一寄存器分组中寄存器的个数为2,剩下REG1作为第二寄存器分组,REGN作为第三寄存器分组。之后,执行S709。
具体的,得到的第一寄存器分组为
S709:对上述S704、S705、S707和S708步骤中生成的第一寄存器分组G,分别生成向量形式的中间代码,每个第一寄存器分组对应一条向量形式的中间代码。对S705、S707、S708步骤中的第二寄存器分组或第三寄存器分组,生成标量形式的中间代码。
例如,若上述offset为16字节对齐,则寄存器号i为奇数,其寄存器分组G的一般形式为生成如下向量形式的中间代码:
若上述offset不为16字节对齐,则寄存器号i为偶数,其寄存器分组G的一般形式为生成如下向量形式的中间代码:
由于offsetnew=offset+8,因此,上述寄存器号为奇数和寄存器号为偶数的一般形式可以统一表述为:则生成如下向量形式的中间代码:
对于上述S705中的第二寄存器分组REGN,生成如下标量形式的中间代码:
对于上述S707中的第二寄存器分组REG1,生成如下标量形式的中间代码:
对于上述S708中的第三寄存器分组REGN,生成如下标量形式的中间代码:
S710:对上述向量形式的中间代码附加第一调试信息,对上述标量形式的中间代码附加第二调试信息。
可选的,继续按照上述S709的例子,附加了第一调试信息后的中间代码为:
上述S709附加了第二调试信息后的REG1和REGN对应的标量形式的第二中间代码分别为:
REG1对应的标量形式的第二中间代码:
REGN对应的标量形式的第二中间代码:
S711:根据上述向量形式的中间代码,生成向量访存指令的第一汇编代码;根据上述标量形式的中间代码,生成标量访存指令的第二汇编代码。
具体的,继续按照上述S709中的例子,第一汇编代码如下:
REG1对应的第二汇编代码如下:
REGN对应的第二汇编代码如下:
S712:根据上述S710中的第一调试信息生成第一汇编代码的第一调试伪指令,根据上述S710中的第二调试信息生成第二汇编代码的第二调试伪指令,并将包含有第一调试伪指令和第一汇编代码输出给目标处理器以及将包含有第二调试伪指令和第二汇编代码输出给目标处理器。
具体的,继续按照上述S709中的例子,最后得到的包含有第一调试伪指令的向量访存指令为:
最后得到的REG1对应的包含有第二调试伪指令的标量访存指令为:
最后得到的REGN对应的包含有第二调试伪指令的标量访存指令为:
综上所述,上述S701-S712的步骤过程就是生成函数序中用于保存寄存器的向量访存指令的具体过程。
本发明实施例的提供的函数的访存优化编译方法,通过对函数序中需要保存的寄存器进行分组,并根据分组的不同情况生成向量形式的中间代码和标量形式的中间代码,即利用一条向量访存指令代替现有技术中多条标量访存指令来保存寄存器,从而大大减少了函数序或函数跋中的指令数量,节省了存储指令的空间,并且利用向量访存指令具有多个源或目标寄存器的特点,也很大程度上提高了计算机的访存效率,并减少了寄存器的压力,进一步还可以为研发人员调试程序提供帮助。
本领域普通技术人员可以理解:实现上述各方法实施例的全部或部分步骤可以通过程序指令相关的硬件来完成。前述的程序可以存储于计算机可读取存储介质中。该程序在执行时,执行包括上述各方法实施例的步骤;而前述的存储介质包括:ROM、RAM、磁碟或者光盘等各种可以存储程序代码的介质。
图8为本发明提供的函数的访存优化编译装置实施例一的结构示意图。该装置可以为上述方法实施例中的编译器,也可以集成在编译器中。如图8所示,该装置包括:分组模块10、确定模块11、第一生成模块12和第二生成模块13。
其中,分组模块10,用于根据与待编译函数的函数序或函数跋相关的同一类型的寄存器的宽度和目标处理器中的向量访存指令的访存宽度,对所述同一类型的寄存器进行分组,获取至少一个寄存器分组;其中,每个所述寄存器分组中包括至少一个寄存器;
确定模块11,用于根据所述分组模块10获得的每个所述寄存器分组中寄存器的个数确定每个所述寄存器分组对应的中间代码的类型;
第一生成模块12,用于在所述确定模块11确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码,则对所述寄存器分组生成一条向量 形式的第一中间代码;
第二生成模块13,用于根据所述第一生成模块12生成的所述第一中间代码生成第一汇编代码,并将所述第一汇编代码输出给所述目标处理器。
本发明实施例提供的函数的访存优化编译装置,可以执行上述方法实施例,其实现原理和技术效果类似,在此不再赘述。
进一步地,上述确定模块11,具体用于根据所述分组模块10获得的所述寄存器分组中的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,确定每个所述寄存器分组对应的中间代码的类型。
更进一步地,上述确定模块11,具体用于判断所述分组模块10获得的所述寄存器分组中的寄存器的个数是否等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,若是,则确定所述寄存器分组对应的中间代码的类型为向量形式的中间代码;若否,则根据所述寄存器分组的个数和所述向量访存指令的向下兼容结果,确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码,或,向量形式的中间代码。
图9为本发明提供的函数的访存优化编译装置实施例二的结构示意图。在上述图8所示实施例的基础上,所述装置还包括:第一调试信息附加模块14,用于在所述第一生成模块12对所述寄存器分组生成一条向量形式的第一中间代码之后,为所述第一中间代码附加第一调试信息;所述第一调试信息用于指示所述寄存器分组中的寄存器被保存在栈中的位置。
进一步地,所述第二生成模块13,具体用于根据所述第一调试信息生成第一调试伪指令,并将所述第一调试伪指令和所述第一汇编代码输出给所述目标处理器。
本发明实施例提供的函数的访存优化编译装置,可以执行上述方法实施例,其实现原理和技术效果类似,在此不再赘述。
图10为本发明提供的函数的访存优化编译装置实施例三的结构示意图。在上述图8或图9所示实施例的基础上,进一步地,上述装置还包括:第二调试信息附加模块15;其中,所述第一生成模块12,还用于在所述确定模块11确定所述寄存器分组对应的中间代码的类型为标量形式的中间代码时,对所述寄存器分组中的每个寄存器分别生成一条标量形式的第二中间代码;
所述第二调试信息附加模块15,用于为所述第一生成模块12生成的所 述第二中间代码附加第二调试信息;所述第二调试信息用于指示所述寄存器分组中的寄存器被保存在栈中的位置;
所述第二生成模块13,还用于根据所述第二中间代码生成第二汇编代码,并根据所述第二调试信息生成第二调试伪指令,并将所述第二调试伪指令和所述第二汇编代码输出给所述目标处理器。
需要说明的是,图10示出的结构示意图仅示出的是基于图9所示的实施例的结构,其只是作为一种示意,当然,图10也可以基于图8所示实施例的结构,本发明在此未示出。
图11为本发明提供的函数的访存优化编译装置实施例四的结构示意图。所述待编译函数涉及的同一类型的寄存器的总个数为N,所述N为大于等于2的正整数;在上述图8或图9或图10所示实施例的基础上,进一步地,所述分组模块10,具体包括:排序单元101、判断单元102和分组单元103。
排序单元101,用于对所述同一类型的寄存器按照从小到大的顺序进行编号;
判断单元102,用于判断所述同一类型的寄存器中的每个寄存器在所述栈中的保存地址相对于栈基址寄存器sp的第一偏移是否均为M字节对齐,获得第一判断结果;其中,所述M为所述向量访存指令的访存宽度;
分组单元103,用于根据所述判断单元102的所述第一判断结果对所述同一类型的寄存器进行分组,获取所述寄存器分组。
需要说明的是,图11示出的结构示意图仅示出的是基于图10所示的实施例的结构,其只是作为一种示意,当然,图11也可以基于图8或图9所示实施例的结构,本发明在此未示出。
可选的,作为其中的一种可能的实施方式,所述分组单元103,具体用于在所述判断单元102的所述第一判断结果为每个所述第一偏移均是M字节对齐时,根据所述N、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度对所述同一类型的寄存器进行分组,获取所述寄存器分组。
在这种实施方式下,进一步地,所述分组单元103,具体用于在所述判断单元102的所述第一判断结果为每个所述第一偏移均是M字节对齐时,指示所述判断单元102继续判断所述N是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若整除,则对所述N个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器;
若不能整除,则对前(N-P)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据后P个顺序编号的寄存器确定第二寄存器分组;其中,所述P为所述N除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值。
可选的,作为其中的另一种可能的实施方式,所述分组单元103,还用于在所述判断单元102的所述第一判断结果为至少一个所述第一偏移是M字节不对齐时,确定不对齐的寄存器的个数,并根据所述N、所述不对齐的寄存器的个数、所述向量访存指令的访存宽度和所述同一类型的寄存器的宽度,对所述同一类型的寄存器进行分组,获取所述寄存器分组。
在这种可能的实施方式下,所述分组单元103,具体用于在所述判断单元102的所述第一判断结果为至少一个所述第一偏移是M字节不对齐时,确定第二偏移为所述第一个寄存器相对于所述栈基址寄存器sp的第一偏移加上不对齐的寄存器的个数T乘以所述不对齐的寄存器的宽度的乘积的和,并继续指示所述判断单元102判断所述N减去所述T的差值是否可以整除所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值;
若整除,则对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组;其中,所述第一寄存器分组中寄存器的个数等于所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值,所述第一寄存器分组中的寄存器为顺序编号的寄存器;
若不整除,则对后(N-T)个顺序编号的寄存器进行分组,获得至少一个第一寄存器分组,并根据前T个顺序编号的寄存器确定第二寄存器分组,并根据后Q个顺序编号的寄存器确定第三寄存器分组;其中,所述Q为所述(N-T)的差值除以所述向量访存指令的访存宽度除以所述同一类型的寄存器的宽度的商值的余数,所述第一寄存器分组中寄存器的个数等于所述向量访存指令 的访存宽度除以所述同一类型的寄存器的宽度的商值。
本发明实施例提供的函数的访存优化编译装置,可以执行上述方法实施例,其实现原理和技术效果类似,在此不再赘述。
最后应说明的是:以上各实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述各实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分或者全部技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的范围。