亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        面向RISC-V處理器的GCC移植與優(yōu)化

        2021-09-15 11:20:34唐俊龍禹智文劉遠治肖仕勛鄒望輝
        計算機應用與軟件 2021年9期
        關(guān)鍵詞:編譯器寄存器移位

        唐俊龍 禹智文 劉遠治 肖仕勛 鄒望輝

        1(長沙理工大學物理與電子科學學院 湖南 長沙 410114)

        2(柔性電子材料基因工程湖南省重點實驗室 湖南 長沙 410114)

        0 引 言

        GCC(GNU Compiler Collection)是由 GNU 工程開發(fā)的編譯器,支持C/C++、Java、Fortran等多種前端編程語言和x86、i386、MIPS等后端體系結(jié)構(gòu),決定了源程序翻譯為目標代碼的翻譯效率與質(zhì)量,直接影響了處理器系統(tǒng)的整體性能[1]。編譯器是一種應用服務(wù),應用不同要求的功能不一樣,每次重新設(shè)計一套編譯器非常耗時,而利用GCC前后端可擴展的特點,復用前端代碼與移植GCC后端到特定體系結(jié)構(gòu)的目標平臺是一種省時、有效的方法。因此,GCC的移植與優(yōu)化是嵌入式交叉開發(fā)的熱點[2-4]。

        加州大學伯克利分校開發(fā)的精簡、開放、模塊化開源指令集架構(gòu)RISC-V,與CISC指令集相比,更適用于微型嵌入式系統(tǒng)。GCC為RISC-V提供后端接口,但在目標平臺上運行需要針對新體系特點做相應的后端移植。機器描述是主要的后端移植方法,一種是參照與目標體系相近的體系結(jié)構(gòu),修改GCC源碼得到目標機器描述文件,開發(fā)周期短但需熟知各種體系結(jié)構(gòu),要求較高[5];另一種是從零開始逐層編寫機器描述,逐步遞進式地移植,便于修改和調(diào)試[6]。GCC移植成功后,直接編譯源碼生成的可執(zhí)行目標代碼體積大而質(zhì)量低,微型嵌入式系統(tǒng)內(nèi)存資源有限需要高效的目標代碼[7],需要優(yōu)化GCC。目前廣泛應用的編譯優(yōu)化技術(shù)有寄存器分配[8]、公共子表達式刪除[9]和窺孔優(yōu)化[10]。公共子表達式刪除常用于前端優(yōu)化,RISC-V處理器的內(nèi)存訪問指令簡潔,使用專用的load/store指令訪問內(nèi)存,寄存器操作類指令的使用頻率較低,窺孔優(yōu)化能更大地提升RISC-V處理器的編譯器性能。窺孔優(yōu)化主要有冗余指令刪除、指令替換、強度削弱和利用特殊指令四種方式[11-13]。文獻[14]中移位替換乘法的指令替換方法減少編譯運行時間10%,未優(yōu)化移位操作自身空間。文獻[15]的冗余指令刪除方法刪除重復使用的load/store指令,降低了編譯運行的功耗約13%,而RISC-V處理器具有簡潔的load/store訪存指令,冗余指令少。文獻[16]利用乘加指令的特殊指令方法提高了指令并行化程度,編譯運行時間減少,而目前RISC-V處理器暫未設(shè)計乘加單元。文獻[14-16] 使用靜態(tài)窺孔方法,未優(yōu)化編譯生成目標代碼體積,算法效率有待提升。

        本文利用宿主機-虛擬機的模式,在Linux系統(tǒng)虛擬機環(huán)境下進行嵌入式交叉開發(fā),使用機器描述的后端移植方法,參照ARM體系結(jié)構(gòu),修改GCC源碼得到目標機器描述文件,移植GCC到RISC-V處理器平臺,正確生成riscv-none-embed-gcc編譯器。采用強度削弱的窺孔優(yōu)化方法對riscv-none-embed-gcc進行優(yōu)化,解決中間代碼生成過程中寄存器低效使用而造成CPU計算代價高的問題,縮小目標代碼體積,提高了目標代碼質(zhì)量。

        1 GCC后端移植機制的建立

        GCC包括語言前端、語言和機器無關(guān)的中間語言及機器相關(guān)的后端代碼三部分,GCC基本結(jié)構(gòu)如圖1所示,語言與平臺的加入相對獨立,具有很強的可移植性。語言前端是GCC處理每種編程語言的代碼,主要完成詞法與語法分析、抽象語法樹(AST)生成及語法樹規(guī)范化(Generic),以AST為前端接口支持不用考慮機器信息的各種編程語言。中間語言(GIMPILE)是AST的中間表示形式。后端的生成器(gen)參考機器描述文件(MD)生成獨立于編程語言的各種體系結(jié)構(gòu)匯編代碼,支持不同目標平臺。GIMPILE與MD-RTL表達的機器描述都是RTL語言,高級語言到目標語言的轉(zhuǎn)換過程更平緩。GCC靈活的結(jié)構(gòu)能夠移植到新目標平臺,它的后端移植核心思想是目標機器描述及引導中間代碼生成和優(yōu)化機制,本文建立的后端移植機制如圖2所示。MD中提取出目標機器的特點引導指令模板與GIMPILE的生成,確保GCC正確翻譯。GIMPILE解析出的指令序列insn1...n與指令模板進行匹配,匹配成功的序列確定為指令輸出,所有序列匹配完成后,提取指令輸出生成匯編代碼。描述處理器的數(shù)據(jù)和指令信息的MD文件設(shè)計是RISC-V處理器進行GCC后端移植的關(guān)鍵。GCC源碼中,數(shù)據(jù)信息以應用二進制接口(ABI)的形式表示,指令信息以RTL模板的形式描述。修改GCC源碼,描述RISC-V與其他體系結(jié)構(gòu)不同的數(shù)據(jù)和指令特點,解決傳統(tǒng)GCC源碼生成的編譯器編譯得到的可執(zhí)行程序不能在RISC-V處理器上運行的問題。

        圖1 GCC基本結(jié)構(gòu)圖

        圖2 GCC后端移植機制

        2 GCC后端移植的實現(xiàn)

        根據(jù)圖2后端代碼生成機制,以C宏和RTL語言分別描述RISC-V的ABI和指令信息特點,編寫機器描述文件,在Linux系統(tǒng)環(huán)境下配置GCC的編譯選項生成riscv-none-embed-gcc編譯器,實現(xiàn)GCC后端移植。

        2.1 機器描述文件的設(shè)計

        設(shè)計機器描述文件是描述RISC-V處理器平臺數(shù)據(jù)和指令信息的過程,本文定義數(shù)據(jù)存儲布局、設(shè)計寄存器用法與函數(shù)棧幀和RTL指令模板,分別在riscv.h、riscv.c和riscv.md文件中實現(xiàn)ABI的宏定義、宏相關(guān)的函數(shù)和指令信息。

        ABI包括數(shù)據(jù)的存儲布局和寄存器用法與堆棧,數(shù)據(jù)的存儲布局定義目標平臺的存儲格式、數(shù)據(jù)類型大小和對齊處理,寄存器用法與函數(shù)棧幀確定數(shù)據(jù)在棧幀空間的存儲位置。

        (1) 存儲格式定義。通用體系結(jié)構(gòu)的GCC規(guī)定值0、1分別表示小端、大端存儲格式,RISC-V指令僅支持小端格式,位、字節(jié)和字大小數(shù)據(jù)的小端格式都用后綴_BIG _ ENDIAN表示,定義BITS_BIG_ENDIAN、BYTES _BIG_ ENDIAN和WORDS_BIG_ENDIAN宏值為0。

        (2) 數(shù)據(jù)類型定義。本文移植的編譯器為C編譯器,RISC-V 基本指令集的C程序數(shù)據(jù)類型特點如表1所示。編譯器移植的首要工作是根據(jù)表1在GCC源碼中定義數(shù)據(jù)類型及大小,例如:短整型宏定義為#define SHORT_ TYPE_ SIZE 16;指針型宏定義為#define POINTER_SIZE(riscv_abi>=ABI_LP64 ? 64:32)。

        表1 RISC-V的C程序數(shù)據(jù)類型

        (3) 對齊處理。數(shù)據(jù)對齊處理可以減少內(nèi)存浪費,RISC-V指令中函數(shù)參數(shù)在堆棧中對齊位數(shù)應與單字的字節(jié)數(shù)保持一致,函數(shù)入口地址對齊位數(shù)中C擴展指令集為16位,其他為32位。表1中最大數(shù)據(jù)類型long double位寬為128,定義最大對齊位數(shù)為128,以防止內(nèi)存對齊溢出。在riscv.h頭文件中,函數(shù)參數(shù)對齊位數(shù)的宏定義為#define BYTES_PER_WORD(TARGET_RVC ? 4 : 8)和#define PARM_ BOUN DARY BITS_ PER_ WORD,函數(shù)入口地址的宏定義為#define FUNCTION_ BOUNDARY(TARGET_ RVC ? 16:32),最大對齊位數(shù)的宏定義為#define BIGGEST_ALIGNMENT 128。

        (4) 寄存器用法與函數(shù)棧幀的設(shè)計。RISC-V的66個物理寄存器中有19個臨時寄存器t0-t6和ft0-ft11、12個整數(shù)寄存器s0-s11及12個浮點寄存器fs0-fs11。在寄存器間傳輸數(shù)據(jù)能提高RISC-V處理器運算能力,寄存器用法直接關(guān)系到GCC編譯器的功能正確性。RISC-V臨時寄存器在調(diào)用過程中會破壞,整數(shù)寄存器和浮點寄存器在調(diào)用后保持不變,本文設(shè)計將t0-t6和ft0-ft11寄存器的值保存在調(diào)用者的棧幀中,s0-s11和fs0-fs11寄存器的值保存在被調(diào)用者的棧幀中,以保證寄存器后續(xù)的存儲使用,函數(shù)棧幀布局如圖3所示。棧幀指針指向棧底,硬件棧幀指針指向被調(diào)用函數(shù)開始的地址,幀指針指向棧頂,各指針的初始化值根據(jù)圖3的布局位置確定,定義棧指針、硬件棧幀指針和幀指針的宏STACK_POINTER_REGNUM、HARD_FRAME_POINTER_ REGNUM和 FRAME _POINTER_REGNUM的值分別為2、8和65。棧幀空間創(chuàng)建、寄存器保存操作在riscv.c文件中分別由riscv_compute_frame_info()、riscv_save_restore _fn()函數(shù)實現(xiàn),函數(shù)棧幀的設(shè)計流程如圖4所示。

        圖3 RISC-V函數(shù)棧幀布局

        圖4 函數(shù)棧幀設(shè)計流程

        指令信息包括指令的機器模式、指令名稱、屬性、常量和約束,不同體系結(jié)構(gòu)的指令信息差異較大,本文根據(jù)目標平臺的指令信息,在MD文件中使用RTL語言設(shè)計加法、乘法、除法、邏輯和跳轉(zhuǎn)等指令模板。圖5為指令模板中的加法指令模板,表示操作數(shù)1與操作數(shù)2相加,計算結(jié)果保存在操作數(shù)0所在寄存器中,“register_operand”類型的操作數(shù)1與“arith”類型的操作數(shù)2滿足64位目標機器條件,按照RTL模板匯編輸出“add%i2w %0,%1,%2”,否則輸出“add%i2 %0,%1,%2”。其中:“addsi3”為指令名稱;“SI”為機器模式;“match_opeand”用于描述該操作數(shù)的匹配條件;“register_operand”和“arith_operand”表示操作類型。

        圖5 RISC-V加法指令模板

        2.2 riscv-none-embed-gcc編譯器的生成

        RISC-V指令集包括基本I整數(shù)集以及A、M、F、D、C等擴展指令集,本文根據(jù)所移植編譯器為32位版本的需求,選擇M、A、D、F指令集,確定參數(shù)組合RV32IMADF。機器描述文件建立后,加入RISC-V處理器的CPU類型(cpu_type=riscv)至config.sub文件中的riscv*)模塊,添加機器型號(Basic _machine=riscv)至config.gcc文件作為GCC的識別端口。在Linux系統(tǒng)下配置abi和arch的編譯參數(shù)選項分別為ilp32 和rv32imadf,編譯安裝移植后的GCC源碼,生成riscv-none-embed-gcc編譯器。

        3 強度削弱的窺孔優(yōu)化實現(xiàn)

        許多數(shù)據(jù)密集型應用程序中廣泛使用乘法和數(shù)據(jù)移位操作,計算量大且直接編譯生成的目標代碼體積大。部分乘法操作可以用移位的方式替代,同時移位操作自身也存在優(yōu)化的可能。本文基于RISC-V處理器簡潔的內(nèi)存讀寫和跳轉(zhuǎn)指令的特點,采用強度削弱的窺孔優(yōu)化方法對數(shù)據(jù)密集型應用程序進行強度削弱,挖掘移位操作的優(yōu)化空間,以移位化簡的方式簡化RTL中間代碼級的指令,利用計算代價較小的指令替換代價較大的指令,減少指令執(zhí)行時間和寄存器資源占用,優(yōu)化編譯器,減小目標代碼體積,節(jié)省處理器存儲空間。

        圖6、圖7是優(yōu)化前后操作數(shù)a左移常數(shù)位(a<

        圖6 優(yōu)化前移位操作

        圖7 強度削弱的窺孔優(yōu)化設(shè)計

        圖6為ARM體系結(jié)構(gòu)中操作數(shù)a經(jīng)三次移位實現(xiàn)左移const位的一個過程。CPU先從內(nèi)存中讀取操作數(shù)a,寫入寄存器1。運算單元依次從寄存器1、2、3讀寫數(shù)據(jù)并移動[b]、[c]、[d] 位,結(jié)果寫入寄存器4,讀寄存器4中的值寫回內(nèi)存,完成操作數(shù)a左移const位的操作。CPU進行了一次內(nèi)存讀和寫,三次寄存器讀和寫操作,占用4個寄存器資源,使用5條指令,計算代價為10。圖7為本文實現(xiàn)強度削弱的窺孔優(yōu)化設(shè)計,確保移位數(shù)為正數(shù) [e]=[c]-[d]([c]>[d]),保證GCC中寄存器3與寄存器4的識別標號(REGNO)一致,運算單元依次從寄存器1、2讀寫數(shù)據(jù)并移動[b]、[e]位,結(jié)果寫入寄存器4。強度削弱后三次移位操作簡化為兩次移位操作,減少了一次寄存器讀寫、一個寄存器和一條指令,計算代價減少2。圖8為強度削弱程序設(shè)計流程,代碼實現(xiàn)中以define_ peep hole2定義窺孔優(yōu)化。

        圖8 強度削弱程序設(shè)計流程

        4 移植驗證與優(yōu)化測試

        由于語言前端的多樣性和目標平臺結(jié)構(gòu)的特殊性,國內(nèi)外目前尚無標準、系統(tǒng)、通用的編譯器測試方法。C語言具有自身的屬性,C編譯器的正確性測試主要是C語言中語法、語義的符合性的寬度測試與語法、語義間任意復雜的組合性的深度測試。寬度測試確保編譯器對源程序中各類語法和語義都無遺漏地進行測試;深度測試保證編譯器能正確處理語法和語義的嵌套、組合問題[18]。本文在PC機Win10 64位系統(tǒng)(宿主機)和Ubuntu16.04 64位系統(tǒng)(虛擬機)實驗環(huán)境下結(jié)合設(shè)計的寬度測試用例、深度測試用例和完整的C程序驗證編譯器功能的正確性,并采用GCC內(nèi)專用測試程序驗證編譯器功能的通用性;利用GCC內(nèi)定點運算、浮點運算、循環(huán)計數(shù)和函數(shù)嵌套四種程序測試編譯器的優(yōu)化效果。

        4.1 編譯器功能的驗證

        C89標準的語義約束繁多,本文寬度測試僅以下標數(shù)組和結(jié)構(gòu)體語義約束為例,下標數(shù)組約束中數(shù)組的一個表達式類型應為指向?qū)ο蟮闹羔橆愋?;結(jié)構(gòu)體約束中結(jié)構(gòu)體的“—>”算符的第一操作數(shù)類型應為指向限定或非限定結(jié)構(gòu)的指針。測試用例如表2所示,每種約束設(shè)計一組正確和錯誤用例進行對比,數(shù)組和結(jié)構(gòu)體測試的錯誤用例中,數(shù)組元素類型為常整型,“—>”算符的第一操作數(shù)p的類型是指向int型變量的指針,都不符合語義約束。編譯器能通過正確用例,不能通過錯誤用例,但能產(chǎn)生正確的出錯警告。表3為寬度測試結(jié)果,編譯器功能正確。

        表2 寬度測試用例

        表3 寬度測試結(jié)果

        深度測試結(jié)果如圖9所示,L3段通過jmp指令跳轉(zhuǎn)至L4段,對應源程序中最外層循環(huán)進入第二層循環(huán);L4段通過jle指令跳轉(zhuǎn)至L6段,對應源程序中第二層循環(huán)進入最內(nèi)層循環(huán);L6段中三次je指令跳轉(zhuǎn)至L5段,對應源程序中if條件判斷語句在三層循環(huán)中的訪問;L2段執(zhí)行完后以leave指令結(jié)束,對應源程序中printf輸出函數(shù)執(zhí)行完后跳出循環(huán)體。循環(huán)嵌套的深度測試驗證了編譯器翻譯出匯編代碼的正確性,無出錯警告。

        C源程序循環(huán)部分代碼: for(hund=1;hund<5;hund++) { for(ten=1;ten<5;ten++) {for(single=1;single<5;single++) {if(hund!=ten&&hund!=single&&single!=ten) {printf("%d,%d,%d ",hund,ten,single); } } } }編譯生成的部分匯編代碼:.LFB0: ........ jmp .L3.L6: movl -8(%rbp), %eax cmpl -4(%rbp), %eax je .L5 movl -8(%rbp), %eax cmpl -12(%rbp), %eax je .L5 movl -12(%rbp), %eax cmpl -4(%rbp), %eax je .L5.L5: addl 1, -12(%rbp).L4: cmpl 4, -12(%rbp) jle .L6 addl 1, -4(%rbp).L3: movl 5, -4(%rbp) movl 1, -12(%rbp) jmp .L4.L2: movl 0, %eax leave .cfi_def_cfa 7, 8

        圖9 深度測試結(jié)果

        利用objdump[19]反匯編工具查看C程序編譯后生成的匯編代碼是否滿足匯編語法規(guī)則,是否具有C源程序的功能,如圖10所示。對比C程序與匯編代碼,編譯器成功按照RTL模板逐條翻譯出目標代碼,編譯器功能正確。

        C程序:#includeint main(){int a=2,b;b=a<<4;printf(“b=%d ,b);return 0;}編譯生成的匯編代碼:Disassembly section .text:0000 00 00 00 00 0000

        : push %rbp mov %rsp,%rbp sub 0x10,%rsp movl 0x2,-0x8(%rbp) mov -0x8(%rbp),%eax shl 0x4,%eax mov %eax,-0x4(%rbp) mov -0x4(%rbp),%eax mov %eax,%esi mov 0x0,%edi mov 0x0,%eax callq 2c mov 0x0,%eax leaveq retq

        圖10 移位程序編譯結(jié)果

        利用DejaGnu[20]工具對i386、ia64等平臺中24 538個專用測試程序進行了編譯,測試結(jié)果預期通過數(shù)expected passes為24 538,預期失敗數(shù)unexpected failures為0,未測試例程untested testcases為5,移植后的GCC編譯器成功翻譯所有專用測試程序,具有預處理、錯誤警告等通用功能。

        4.2 窺孔優(yōu)化效果的測試

        編譯生成的匯編代碼體積是衡量編譯器性能的重要指標之一。本文采用DejaGnu開源測試工具,關(guān)閉宿主機上虛擬機以外的服務(wù)進程,保證riscv-none-embed-gcc優(yōu)化前后的測試環(huán)境一致,排除PC主機進程對實驗結(jié)果的影響。利用優(yōu)化前后的riscv-none-embed-gcc測試GCC源碼內(nèi)四種移位運算程序test1- 4,記錄各自生成的匯編代碼體積,并統(tǒng)計體積變化。riscv-none-embed-gcc在強度削弱窺孔優(yōu)化前后,生成的匯編代碼體積(字節(jié)為單位)如表4所示,四種目標代碼體積縮小約11%;浮點運算程序存儲內(nèi)存較大,優(yōu)化程度好于定點運算程序;多次調(diào)用窺孔優(yōu)化后函數(shù)嵌套調(diào)用程序效果突出。

        表4 匯編代碼體積測試

        5 結(jié) 語

        嵌入式微處理器采用開源可擴展的RISC-V指令集,設(shè)計靈活簡潔。處理器、交叉編譯器和操作系統(tǒng)構(gòu)成嵌入式交叉開發(fā)完整體系,不同的處理構(gòu)需要不同的交叉編譯器。最大化RISC-V處理器在Linux系統(tǒng)下的性能,傳統(tǒng)的GCC需要移植與優(yōu)化。本文分析了GCC的基本結(jié)構(gòu),建立了機器描述引導目標代碼生成的GCC后端移植機制,完成了RISC-V體系結(jié)構(gòu)數(shù)據(jù)與指令信息的機器描述,實現(xiàn)了GCC的移植,生成了riscv-none-embed-gcc編譯器并進行優(yōu)化。利用objdump反匯編工具驗證了riscv-none-embed-gcc的正確性與通用功能。選用GCC源碼內(nèi)四種數(shù)據(jù)密集型應用程序,利用DejaGnu工具測試了優(yōu)化效果,匯編代碼體積縮小約11%。文中編譯器的移植與優(yōu)化方法節(jié)省了微型嵌入式系統(tǒng)的資源,適用于RISC-V處理器面向數(shù)據(jù)密集型的應用和RISC-V編譯工具鏈的開發(fā)與設(shè)計。

        猜你喜歡
        編譯器寄存器移位
        Lite寄存器模型的設(shè)計與實現(xiàn)
        計算機應用(2020年5期)2020-06-07 07:06:44
        再生核移位勒讓德基函數(shù)法求解分數(shù)階微分方程
        基于相異編譯器的安全計算機平臺交叉編譯環(huán)境設(shè)計
        大型總段船塢建造、移位、定位工藝技術(shù)
        Σ(X)上權(quán)移位算子的不變分布混沌性
        分簇結(jié)構(gòu)向量寄存器分配策略研究*
        多指離斷手指移位再植拇指25例
        通用NC代碼編譯器的設(shè)計與實現(xiàn)
        高速數(shù)模轉(zhuǎn)換器AD9779/AD9788的應用
        一種可重構(gòu)線性反饋移位寄存器設(shè)計
        精品国模人妻视频网站| 国产精品乱码在线观看| 中文字幕在线观看国产双飞高清 | 亚洲综合天堂av网站在线观看| 色橹橹欧美在线观看视频高清| 久草视频福利| 人妻熟女中文字幕在线视频| 国产肥熟女免费一区二区| 内射爽无广熟女亚洲| 欧美亚洲日韩国产区| 日韩精品一区二区av在线| 亚州终合人妖一区二区三区| 久久综合丝袜日本网| 在线高清精品第一区二区三区| 日韩在线精品视频观看| 日本熟女人妻一区二区| 免费国产黄网站在线观看可以下载| 国产在线手机视频| 国产一品二品三品精品久久| 国产成人91久久麻豆视频| 欧美交换配乱吟粗大25p| 午夜国产一区二区三区精品不卡| 日本一区二区在线播放| 国产午夜片无码区在线播放 | 一区两区三区视频在线观看| 欧美高清精品一区二区| 67194熟妇在线永久免费观看| 精品无吗国产一区二区三区av| 亚洲肥婆一区二区三区| 国产两女互慰高潮视频在线观看| 日韩AV不卡一区二区三区无码| 精品中文字幕日本久久久| 在线观看亚洲第一黄片| 草草久久久无码国产专区| 色播中文字幕在线视频| 尤物精品国产亚洲亚洲av麻豆| 波多野结衣的av一区二区三区| 国产亚洲精品自在久久蜜tv| 色婷婷一区二区三区77| 天天摸天天做天天爽水多| 少妇太爽了在线观看|