面向编译器移植和优化的耦合寄存器实现方法

文档序号:6382815阅读:207来源:国知局
专利名称:面向编译器移植和优化的耦合寄存器实现方法
技术领域
本发明涉及编译器开发和移植技术领域,特别是一种面向编译器移植和优化的耦合寄存器的方法,还涉及编译器中间表达式(intermediaterepresentation)的设计,针对具有耦合寄存器性质的芯片的后端优化和寄存器分配。
背景技术
1.1.编译器的移植编译器是现代计算机系统的基本组成部分之一。从功能上看,一个编译器就是一个语言翻译程序。它把一种源语言翻译为目标语言的等价程序。编译器完成从源程序到目标程序的翻译工作是一个复杂的整体过程。从概念上讲,一个编译器的整个工作过程是划分成阶段进行的,每个阶段将源程序的一种表示形式转换成另一种表示形式,每个阶段进行的操作在逻辑上是紧密联系在一起的。
常常把编译的过程分为前端(front end)和后端(back end)。前端阶段的工作主要依赖于源语言而与目标机器无关。通常这些阶段包括词法分析,语法分析,中间代码生成等,某些优化工作也可以在前端做,包括与前端每个阶段相关的出错处理和符号表管理。后端工作主要指那些依赖于目标机而一般不依赖源语言,只与中间代码有关的那些阶段,即目标代码生成,以及相关的出错处理和符号表操作。而现代的编译器还有中端(middle end),中端介于前端和后端之间,其中间表达既包含源语言的信息也包含机器相关的信息,这为某些特定的编译优化提供了机会。
若按照前面所提到的组合方式实现编译器,可以设想,某一编译器的前端加上相应不同的后端则可以为不同的机器构成同一个源语言的编译器。也可以设想,不同语言编译的前端生成同一种中间语言,再使用一个共同的后端,这可以为同一机器生成几个语言的编译器。让不同的前端使用同一后端,从而得到一个机器上的几个编译器,也是很吸引人的。但是,由于不同语言,不同机器的着眼点有区别,要实现这样上面谈及的移植并不是一件很容易的事情。
虽然支持多语种的编译系统满足了快速开发多种编译器的需求,但是仍然不能适应计算机硬件不断更新换代的飞速发展,虽然早在七十年代末,八十年代初,国内外便有不少人致力于研究支持多语种多目标机的编译系统,但是由于受实际需求的限制,停留于理论研究与实验阶段,并没有形成有效的、实用的编译系统,进入八十年代后期,随着国外各种软件公司的兴起以及各种计算机芯片不断推陈出新,研制多目标机的编译系统显得越来越重要,编译器的开发者们认识到只有支持多语种多目标机编译系统才具有生命力和竞争价值,这种系统实际上是开发编译器的基础平台,它所采用的技术代表着编译技术发展的方向。
中间表达式作为编译器的核心部分,其设计关系到一个编译器的健壮性和可移植性。对于不同的语言和目标机器中间表达式的设计也各异。
在编译器的分析与综合模型中,前端把源程序翻译成中间表示,后端从中间代码产生目标代码。与目标语言有关的细节尽可能限制到后端。虽然源程序可以直接翻译生成目标代码,但使用独立于源程序的中间形式的好处是A)移植比较容易。开发新机器的后端集成到现成的前端上,可以得到不同机器的编译器。
B)独立于机器的代码优化现在流行的做法是对中间表达式也采用分层的形式,不同形式往往取决于它在前端和后端之间的位置。如,对比较高层的中间表示,可以保留类似于数组的形式,或者可以有对一个数据对象的操作。然而到了低层的中间表示,对数组的访问就必须转换成类似机器指令的形式,要有显式的地址和偏移操作。
中间层次的中间表示通常要反映源语言和目标机器的信息,底层的要尽量包含目标体系结构的信息,所以往往是机器相关的;但是与最终生成的汇编码还是存在着差别。底层的中间表示通常还要包含更多的一些信息提供给代码优化,指令调度等。而且要保证这些接口能够被清晰而正确的引用。现代的编译器中往往包含有多层的中间表示。可见,中间表示的设计也是编译器开发中重要的一个技术环节。
1.2.耦合寄存器在某些32位的机器上(如mips r4000)为了实现64位的浮点操作,硬件根据某些状态寄存器的值在32位或64位模式下切换(根据芯片的设计不同,切换的条件可能会不同,但是实现的方式是一致的)。如果机器进入64位模式,对某些64位的浮点数(通常是double类型),会使用两个32浮点寄存器来存放此浮点数,相应的64位浮点指令也会把这两个寄存器看做一个整体来操作,把其操作结果写回到一个或两个浮点寄存器中去。但是指令中不会显示出现两个寄存器,一般的做法是用其中的一个寄存器(以寄存器号来区别,通常是用寄存器号为偶数的寄存器)来代表这一对寄存器。
如果在此芯片上运行的操作系统对应用二进制接口(ABI,ApplicationBinary Interface)的定义不同,在64位的模式下32位的浮点数据的放置也会不一样,例如参数传递。
以上仅以浮点操作为例,整数操作的限制往往没有这样的限制,在32位的机器上做64位的浮点操作没有对寄存器的使用没有限制,不需要按寄存器对使用,同时其64位的操作都是用32位的整数指令来实现的。当然,根据芯片设计的不同,也许会有差异。

发明内容
本发明的目的在于提供一种面向编译器移植和优化的耦合寄存器的方法。
基于具有耦合寄存器芯片的编译器开发和移植,其中间表达式中对耦合寄存器的描述必须面向编译优化和寄存器分配。编译器中间表达式中对寄存器的描述,以下简称为TV(temporary variable)图1。
针对具有耦合寄存器(pair register)特性的芯片的编译器移植和优化中,如何在编译器中准确高效描述耦合寄存器信息,同时如何为指令调度(instruction scheduling)和寄存器分配(register allocation)提供支持,是影响其编译器性能和可移植性的重要因素之一。本发明提出一种新型的面向编译器移植和优化的耦合寄存器实现方法,此方法基于编译器的中间表达式(intermediate representation),可以充分而完整地描述寄存器的各种信息。如寄存器的奇偶性,不同寄存器之间相关联的耦合信息等。并且控制实现的开销。同时面向编译器的后端优化和寄存器分配,我们采用了一种实用的分层结构,能更准确而高效使用耦合寄存器的信息,可以针对优化和寄存器分配的操作提供相关的信息而不会对原有的接口产生影响。兼顾到编译器的可移植性,不是所有的芯片都采用了耦合寄存器,本方法可以便捷地打开或关闭耦合寄存器信息,或者添加更多的信息,以维护编译器的健壮性和可移植性。其实现的大体流程图如图6所示。
发明技术方案一种面向具有耦合寄存器芯片的编译器,其中间表达式采用一种新型耦合寄存器信息描述方法,其特征是正确,全面描述耦合寄存器信息;同时针对编译器后端优化以及寄存器分配提供支持,采用一种新型的分层式结构,兼顾编译器的移植,使之可以便捷移植到其它的平台上。
能正确,全面描述耦合寄存器信息,其特征是耦合寄存器不仅要能继承所有一般寄存器的属性,而且能够描述耦合寄存器的各种特殊性质和使用限制,如奇偶性。
针对编译器后端优化以及寄存器分配提供支持,采用一种新型分层式结构,其特征是首先能满足编译器中对中间表达式里寄存器信息的各种操作,如对中间表达式中寄存器的复制操作,其次,如果编译器的后端优化或者寄存器分配中对使用了耦合寄存器的指令有了特殊的要求,那么这些信息能被独立正确记录。
所添加的信息不会影响已有信息的使用,即编译器中对一般寄存器的操作不会因此而发生改变,维护原有接口不变,增加编译器的可移植性。
耦合寄存器是某些芯片所具有的特性,如果编译器要具有良好的移植性就必须让耦合寄存器的信息能够被方便地关掉,或者被添加更多其它的信息,同时保证编译器的接口函数不用做过多地修改,维护编译器的健壮性和可移植性。
2.1tv数据结构的扩展tv作为编译器的中间表达式的一部分,必须能记录下寄存器的一般信息,如寄存器号,相关联的符号表项,标志位(flags)......这些是编译器中间表达式设计的核心部分,根据编译器设计的不同而各异,在此不赘述。
2.1.1记录信息的扩展如果编译器面向支持耦合寄存器的芯片,则必须要能高效,正确地加入耦合机器的描述信息。如果此编译器要具有健壮性和可移植性,那么耦合寄存器的信息不能写死在数据结构中。
首先明确我们需要记录的信息A.对给定的TV,必须能够判断是否存在耦合的TV。
B.对给定的TV,能够得到其对应的耦合的TV,并且这个TV有且仅有一个。(对于大多数的芯片来说都是这样的,不排除有例外情况,如某些网络处理器)C.如果给定的TV在寄存器分配之前已经分配了寄存器,例如在那么其相应的耦合寄存器要能够正确指示出合理的寄存器号,这个寄存器号也应该是唯一的。以mips芯片为例,如果给定的寄存器是一个偶数寄存器,寄存器号为r,那么其耦合的寄存器必须为一个奇数的寄存器,寄存器号为r+1(注意不是r-1),反之亦然。
D.如果给定的一组寄存器和耦合寄存器都没有指定寄存器,那么必须指定其中一个为偶数寄存器,另一个为奇数寄存器。我们将之设计为,如果首先被操作TV为偶数,而通过这个TV被查询或者生成出来的与其相对应的TV为奇数。注意,这是我们的一个重要设计。前提是,使用者能够清楚什么应该知道哪个寄存器应该为偶数,哪个为奇数。这个条件可以通过我们后面对所有隐式操作的显示化,以及耦合寄存器的分层结构来保证。
E.如果一个TV没有指定被指定任何耦合寄存器信息,那么按照本编译器对寄存器的要求,与一般的寄存器一同参与分配。
F.记录的信息要能在后端范围内被访问。
2.1.2TV数据结构的扩展按照上节的要求,需要对原TV数据结构扩展,其原则是保证其原有信息的正确性和效率。
保证其原有信息的正确性的特征是记录寄存器一般的信息不丢失,同时要保证添加的耦合信息不和原有的信息冲突。其冲突是保证对以前设计的接口仍然能够访问到正确的值。
保证其原有信息的效率的特征是对于一些设计良好的编译器来说,其某些重要数据结构的各个域的大小是不能随便改变的,例如,某些数据结构是按照机器字对其的,能增加内存使用和访问的效率。
鉴于上面所述的原则,我们采用hash表来扩展TV的数据结构,而不是在原有的TV数据结构上面添加新的域。
首先设计出记录耦合信息的数据结构typedef struct TV_pair_info{TV*TV_pair;//记录耦合的TVTV*tv_pair_dup;//若tv_pair被复制,者指向下一个拷贝,详细请见分层结构INT16 flags;//附加信息的标志void*annot;//注释}TV_PAIR_INFO;标志位的保留值如下#define TV_PAIR_IS_EMPTY 0x0#define TV_PAIR_IS_EVEN 0x0001#define TV_PAIR_IS_ODD 0x0002#define TV_PAIR_IS_HAS_DUP 0x0004/*这个比较特别,指示是否已经做过奇偶设定了*/此设计非常简洁,同时兼顾了可扩展性,其最后一个域void*可以作为注释,或者另外的数据扩展。我们在此数据结构中引入了分层的概念,详情请见下面一节。
此耦合信息通过hash表和原TV信息映射起来,hash key可以根据编译器的不同而各异。如可以使用原TV的序号(在多数编译器中,中间表达式中数据结构都应该有一个全局唯一的序号),或者TV的地址。映射接口如下设置接口TV_MAP_Set(TV_To_Pair_Map,TV,(void*)pair_info)访问接口(TV_PAIR_INFO*)(TV_MAP_Get(TV_To_Pair_Map,TV))注意每次Set和Get的时候,使用的都是void型的指针。应该强制转换为(TV_PAIR_INFO*)。使用void型指针能够保证这个映射接口的可移植性,此映射接口可以提供给其它的部分使用。
2.1.3访问TV的必要接口使用如下的接口可以全面而高效地使用耦合信息。
TV_PAIR_INFO*Get_Pair_Info(TV*tv)得到入口TV耦合寄存器的TV_PAIR_INFO。可以得到耦合寄存器的相关信息,满足记录信息扩展中的A,B,F要求。
TV_PAIR_INFO*Get_Self_Pair_Info(TV*tv)得到入口TV自己的TV_PAIR_INFO,可以查询本寄存器的奇偶性等。满足记录信息扩展中的A,B,F要求。
TV*Get_Pair_TV(TV*tv)返回与作为参数的TV耦合的TV,如果给定的TV没有耦合寄存器,那么返回空。是对前面两个接口的扩展。
TV*Gen_Pair_TV(TV*tv)对入口TV返回一个与之耦合的TV。如果入口TV已经有了耦合TV,那么直接返回。如果没有,建立一个新的返回。满足记录信息扩展中的C,D,F要求TV*Layer_Copy_TV(TV*tv)
对给定的TV,返回一个与之类似的TV,这个操作在编译器的优化和寄存器中非常普遍,如循环展开。我们引入了TV数据结构的分层概念,此接口会在下一节介绍完分层结构后详细介绍。
2.2TV的分层结构针对上节所提到拷贝操作,对TV的数据结构进一步提出一种分层的概念。这里需要提醒注意,下文都是以mips芯片为例子,对浮点偶数寄存器的操作是显式化操作,对浮点奇数寄存器的操作是隐式化操作。目标平台的不同而各异,请根据实际情况而分析。
2.2.1分层概念的前提A.两个耦合寄存器不会分布在两个BB中,因为对其中一个TV定值或者引用,那么相当于对耦合TV做了相同操作,故这两个操作应该在同一个基本块中。
B.如果对某一个TV做了某种优化,那么对耦合TV也会做相同的优化。基于上一条假设,耦合TV之间是有依赖关系的,且在一个BB以内,而且所有的优化都以BB为单位。A,B这两点都可以通过把隐式操作显式化来保证。
C.如果TV已经被分配了偶数寄存器,那么它的拷贝也应该分配偶数寄存器。反之亦然。
D.耦合寄存器的产生如果都是由显示的代码生成,必须注意一点,一定要先生产有偶数寄存器的指令,再生成有奇数寄存器的指令。这一点也是很自然,因为通过显式化操作而实现的隐式寄存器我们可以保证到这一点。
E.对耦合寄存器的copy操作是有序的。见图1F.若A,B为耦合TV,对它们依次被拷贝了n次。那么对它们做某种优化操作opt也同样有类似的顺序i.opt(A),opt(A),opt(A1),opt(A2).......或者ii.opt(A),opt(A1),...,opt(Ak),opt(B),opt(B1),...,opt(Bk),opt(A(k+1)),...opt(A(2k)),opt(B(k+1)),...,opt(B(2k))...
2.2.2TV数据结构中对分层的支持对上一节中提出的TV数据结构和映射机制,加以进一步解释,以图2为例。
1.耦合TV之间用TV_Map映射机制相互访问,可以得到自己和耦合的TV_Pair_Info。
2.一对耦合TV和拷贝之间用一个指针访问。必须提一句,这个指针TV*tv_pair_dup,也是记录在TV_Pair_Info上的,也必须要通过TV_Map访问,详见前面的TV数据结构扩展。
2.2.3分层概念的使用耦合寄存器分层概念是针对在优化和寄存器分配中对某一个TV进行复制操作,如果原TV具有耦合信息,那么就应该拷贝得到一对TV。而且这一对TV应该和原始的TV对具有同样的信息。
以图3为例,A和B是耦合的TV,如果要产生A的拷贝A1,那么同时也要生成一个B的拷贝B1,把A1和B1按照耦合信息耦合起来。
Copy TV的原则是,对有耦合TV拷贝必须要同时拷贝基耦合TV,如果发现其耦合TV已经被拷贝过,说明已经生产了需要的TV,那么就直接得到。反之,就需要同时建立需要的新TV,同时还要建立耦合TV的新拷贝。
最后生产出来的所有拷贝都应该是如图3的层次结构。
2.2.4创建耦合信息的算法下面以对A拷贝为例,A和B存在耦合信息,Ai和Bi分别为A和B的第i个拷贝。其伪算法如下其下所有的接口请参考前面章节(访问TV的必要接口),里面还使用了一个copy()函数,此函数是编译器中对一个TV拷贝的操作,根据编译器中间表达式设计的不同而各异,请采用相应的接口。本发明不赘述。
TV*Layer_Copy_TV(TV*A){layer_of_a=A;/*沿着TV(A)向下的指针,一直遍历到最底层*/
while(layer_of_a->tv_pair_dup){layer_of_a=layer_of_a->tv_pair_dup;}layer_of_b=Get_Pair_TV(layer_of_a);/*如果最底层的A和B都没有指针指向下一层了那么建立一对新的TV,详见图4*/if(layer_of_b->tv_pair_dup==NULL){copy_of_a=copy(a);copy_of_b=gen_pair_tv(copy_of_a);layer_of_a->tv_pair_dup=copy_of_a}else/*如果已经生成了一对新的TV,那么只需要把一个向下的指针连接起来即可,详见图5*/{layer_of_b=layer_of_b->tv_pair_dup;copy_of_a=get_pair_tv(layer_of_b);layer_of_a->tv_pair_dup=copy_of_a;}return copy_of_a;}


图1具有分层结构的耦合TV示意图。
图2分层结构TV的内部表示,包含相互间的指针和映射信息图。
图3对分层结构TV的拷贝操作的最后结果图。
图4复制算法中,对底层耦合TV都没有向下指针的拷贝操作图。
图5复制算法中,对底层耦合TV存在向下指针的拷贝操作图。
图6本发明的实现耦合寄存器的流程图。
图1,具有分层结构的耦合TV示意图,在本图中Ai和Bi是具有耦合性质的TV。上述具有耦合性质的Ai和Bi应该相互两两配对在一起,同时耦合的配对之间还存在层次关系,即耦合的配对之间有着一定的顺序,且层次之间应该能互相访问。此图是上述关系的一个简单表示,耦合TV之间的指针关系以及不同层次的耦合TV对之间的指针关系请参考图2。
图2,分层结构TV的内部表示,包含相互间的指针和映射信息图。指示出,配对的之间通过TV_MAP相互访问,而不同的层次之间用指针访问。
图3,对分层结构TV的拷贝操作的最后结果图。耦合的A和B在两次拷贝操作以后所生成了两个新的耦合TV,A1和B1,A2和B2。两次拷贝操作所生成的结果是具有分层结构的耦合TV对。
图4,复制算法中,对底层耦合TV都没有向下指针的拷贝操作图。如果在复制算法中,底层耦合TV都没有向下的指针则说明此为最后一层,那么需要建立一个新层,同时建立一个向下的指针。
图5,复制算法中,对底层耦合TV存在向下指针的拷贝操作图。如果在复制算法中,底层耦合存在向下的指针,则表示已经生成了新的层,那么只需要把向下的指针建立起来即可。
图6,实现耦合寄存器的流程图,包含的步骤为第一步S1,扩展TV数据结构。并不直接修改原TV的数据结构,而是增加一个易于扩展的新数据结构TV_PAIR_INFO并通过hash表访问,以保护原有数据结构的完整性和健壮性。第二步S2,设置和完善访问TV的必要接口。通过对编译器全局实现的考虑,设计必须的接口包括通过TV访问与其对应的TV_PAIR_INFO,其中记录与之耦合的TV的信息;通过TV访问其自身的耦合信息,此信息也供其配对TV通过上一接口访问;耦合的TV之间相互的直接访问;对给定的TV进行拷贝的操作,即对给定的TV,返回一个与之类似的TV,返回的TV的拷贝与原TV之间存在层次关系。第三步S3,判断是否满足分层结构的限制要求,这些要求能保证整个实现的完整性,且能保证编译器其它部分能进行较少的改动,若能够满足,则进行第四步S4;根据所面向的体系结构不同,会有细小的差别,若不能完全满足这些限制条件,则返回第一步完善TV数据结构,并继续第二步完善接口。第四步S4,实现分层结构所需要的算法,因为实现的特殊性,对一些操作的算法需要综合考虑分层结构。
权利要求
1.一种面向具有耦合寄存器芯片的编译器,其中间表达式采用一种新型耦合寄存器信息描述方法,其特征是正确,全面描述耦合寄存器信息;同时针对编译器后端优化以及寄存器分配提供支持,采用一种新型的分层式结构,兼顾编译器的移植,使之可以便捷移植到其它的平台上。
2.、根据权利要求1所述的全面新型耦合寄存器描述方法,能正确,全面描述耦合寄存器信息,其特征是耦合寄存器不仅要能继承所有一般寄存器的属性,而且能够描述耦合寄存器的各种特殊性质和使用限制,如奇偶性。
3.根据权利要求1所述的针对编译器后端优化以及寄存器分配提供支持,采用一种新型分层式结构,其特征是首先能满足编译器中对中间表达式里寄存器信息的各种操作,如对中间表达式中寄存器的复制操作,其次,如果编译器的后端优化或者寄存器分配中对使用了耦合寄存器的指令有了特殊的要求,那么这些信息能被独立正确记录。
4.根据权利要求3所述的分层式结构对可移植性提供支持,其特征是所添加的信息不会影响已有信息的使用,即编译器中对一般寄存器的操作不会因此而发生改变,维护原有接口不变,增加编译器的可移植性。
5.满足权利要求1,2,3的编译器能具有比较好的可移植性,其特征是耦合寄存器是某些芯片所具有的特性,如果编译器要具有良好的移植性就必须让耦合寄存器的信息能够被方便地关掉,或者被添加更多其它的信息,同时保证编译器的接口函数不用做过多地修改,维护编译器的健壮性和可移植性。
6.一种面向编译器移植和优化的耦合寄存器的方法,其步骤如下第一步S1,TV数据结构的扩展;第二步S2,设置和完善访问TV的必要接口;第三步S3,判断是否满足分层结构的限制要求,若是则进行第四步,若否,则返回第一步重新设计;第四步S4,实现分层结构所需要的算法。
全文摘要
本发明涉及编译器开发和移植技术领域的一种面向编译器移植和优化的耦合寄存器的方法,包括步骤S1,TV数据结构的扩展;S2,设置和完善访问TV的必要接口;S3,判断是否满足分层结构的限制要求,S4,实现分层结构所需要的算法。针对具有耦合寄存器特性的芯片的编译器移植和优化中,如何在编译器中准确高效描述耦合寄存器信息,同时为指令调和寄存器分配提供支持,是影响编译器性能和可移植性的重要因素之一。本方法基于编译器的中间表达式,可充分,完整地描述寄存器的各种信息,控制实现的开销,同时为编译器的后端优化和寄存器提供支持。本方法可以便捷地开关或扩展耦合寄存器信息,以维护编译器的健壮性和可移植性。
文档编号G06F9/45GK1560740SQ20041000545
公开日2005年1月5日 申请日期2004年2月19日 优先权日2004年2月19日
发明者刘章林, 石学林, 熊竞, 冯晓兵, 张兆庆 申请人:中国科学院计算技术研究所
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1