?

PowerPC處理器代碼執行順序研究

2022-04-01 06:56
數字通信世界 2022年3期
關鍵詞:編譯器代碼指令

朱 強

(中國航空工業集團公司洛陽電光設備研究所,河南 洛陽 471000)

在型號調試過程中,遇到程序的執行順序與CPU實際執行的順序不完全一致的問題。經過對此問題的進一步研究,發現現代處理器和編譯器會對代碼的執行順序進行一定的調整和優化。本文通過對處理器的架構、流水線執行方式以及編譯器的優化原則等內容進行研究,經過查閱相關手冊,通過在代碼中嵌入同步指令sync以及volatile關鍵字可以保證代碼嚴格按照順序執行[1]。

在進行型號調試時,某總線時序要求先對地址A進行寫操作,然后再對地址B和C分別進行一次讀操作。即需要嚴格按照如下三行代碼順序執行:

由于CPU先執行了讀操作,而后執行了寫操作,與預期的執行順序不一致,造成總線時序錯誤。

1 CPU處理器架構

當前,為了提高CPU處理器的處理速度、指令執行的并行度,大多數CPU都采用多級流水線、亂序執行、分支預測等技術。這些技術的應用極大提高了處理能力。

1.1 流水線技術

在以前處理器設計中,處理器在執行代碼時,按照編譯的匯編語言代碼的順序進行執行,這樣的設計稱為按序執行。

PowerPC E500核采用七級流水線技術,分別是取指令1、取指令2、指令譯碼、指令分發、指令執行、指令完成、結果寫回。

不同的指令的執行周期不同,在e500核中,比如跳轉指令單元(Branch Unit)、簡單運算單元(Simple Unit)的指令可以在一個周期即可完成,而多指令單元(Multiple-cycle IU)則需要4、11甚至35個周期完成。數據加載存儲指令單元(Load/store Unit)執行一般需要3個周期。如圖1所示。

圖1 PowerPC架構7級流水線架構示意圖

1.2 亂序執行技術

隨著處理性能要求的提高,在設計處理器時為了提高運行速度,一般會采用亂序執行技術。亂序執行技術其本質是違背了源代碼按照順序執行的原則,但是能夠保證最終的運算結果與預期結果是一致的。同時,處理器還設計了多級高速緩存機制,如果在使用過程中,沒有采取相應的措施,處理器最終的運算結果與我們預期的結果不同。

處理器在CACHE中取出指令,會進行相應的分析,找出相互獨立的指令,并將這些相互獨立的指令送到不同的邏輯單元中執行,這樣提高了執行效率。而對于有相互依賴的指令,則按照順序分別執行。

在PowerPC架構處理器中,官方文檔PowerPC?e500 Core Family Reference Manual中提到,在e500核處理器中采用超標量7級流水技術,即一個時鐘周期可以解析兩條指令和執行完兩條指令,指令的完成是按照順序的,指令是并行執行,但是執行是可以是無序的。

需要說明的是,如果語句之間有依賴關系或者同一個時鐘周期能夠更新兩個以上的寄存器時,則CPU不會對代碼的執行順序進行調整,官方文檔對此做了說明:

在前言的案例中,如果將代碼改成:

則CPU執行的順序也會嚴格按照上述代碼執行,這是因為前兩句都是對地址0xef000000進行寫操作然后再進行讀操作。CPU會認為這兩句是有依賴的,因此嚴格按照代碼順序執行。

1.3 處理器的分支預測功能

處理器為了提高同時執行指令的效率,一般會將分支條件里的指令同時取出,同時執行,等到分支條件結果計算完成后,再將錯誤的結果舍棄,這樣可以避免多次跳轉。

上面例子中,如果a不計算出來,t是無法繼續計算的。但是實際上處理器會將三個計算同時執行,當a的值計算后再將不滿足條件的結果舍棄。

在PowerPC架構處理器中同樣具備分支探測和預測功能,但是處理器真正的分支執行是不可預測的,但是能夠保證結果的正確性。

在某些場合下,要求CPU的代碼執行嚴格按照匯編代碼順序執行,例如對某些硬件寄存器的讀寫操作,有嚴格的時序要求。如果CPU還是按照亂序執行,則會出現指令執行與匯編代碼順序不同步問題。

2 編譯器

不僅處理器在設計時考慮亂序執行的情況,編譯器同樣進行亂序優化。相比處理器亂序優化,編譯器亂序執行優化更有優勢,因為編譯器可以在很大范圍內進行源代碼的分析,而處理器則只能分析小部分指令,這樣使得編譯器能夠做出更優的決策。

2.1 編譯器亂序

處理器的預取單元容量和能力有限,每次分析的指令并發范圍較小,但是編譯器能夠對大范圍的代碼進行整體分析,能夠分析出更多的可以并發的指令,并根據處理器特點,對指令進行重排,使得處理器更容易預取和并發執行,有利于提高處理器的亂序并發執行性能。

因此,在現代的編譯器中一般都具備指令亂序優化功能,同時根據指令對存儲器的訪問情況,對指令進行進一步優化,減少對存儲器的訪問,盡量控制在內部寄存器和CACHE中,提高運行速度。另外,編譯器也會根據指令情況,提高CACHE的命中率,因此編譯器如果開啟了優化選項,實際生成的匯編代碼可能與源代碼的執行順序不一致。

但是,不管是處理器還是編譯器的亂序執行,都不應該改變最終的執行結果的正確性,也就是as-ifserial語義。在這種語義的要求下,這就要求對于有依賴的指令或者數據有上下文要求的操作不能改變順序。因此,在編寫單線程代碼時,實際執行的結果是符合預期的。

2.2 編譯器優化選項

GCC編譯器有多個優化選型,這些選項可以設置,編譯器優化的目的是生成的代碼執行時間盡量短,代碼占用的空間也應當盡量小。

編譯器優化過程如下:編譯器讀取設置的優化參數,然后通過語法分析器對源代碼進行翻譯,并抽象成語法樹。語法樹再經過代碼生成器轉換為RTL,然后進行優化。最終得到優化后的匯編代碼或者機器碼。

例如下面的代碼,主函數最后調用求和,在編譯器選項為優化時,編譯器直接將sum函數中的值在編譯時就求出,并將結果放到r3寄存器中,而沒有使用選擇優化選項時,則需要在CPU中執行求和代碼。

圖2 編譯器優化前和優化后的代碼對比示意圖

3 解決方案

3.1 CPU處理器層面

在PowerPC架構處理器中,官方文檔提供了相應的指令,用于顯式強制按照匯編后的代碼順序執行,主要包括isync(指令同步)、mbar(內存屏障)、msync(同步指令)以及eieio等。

msync指令是要求其指令之前的語句必須執行完成,才能取后續的指令。其中指令eieio是經典PowerPC架構的指令集,在book E版本以上中使用mbar指令代替eieio指令,同時也支持eieio指令。

3.2 編譯器層面

對于一些不希望被優化的指令,可以通過volatile關鍵字來抑制,這樣編譯器可以不對相關的變量進行優化。

3.3 驗證測試

經過以上分析,為了防止編譯進行代碼重排序和防止從緩沖中取數據,需要在變量前加volatile進行修飾。同時為了防止CPU執行代碼時并行處理指令導致的亂序問題,需要在代碼處增加同步指令。修改后代碼如下:

經過測試,代碼執行順序正常。

4 結束語

(1)處理器和編譯器為了提高執行效率,會對代碼的執行順序進行重組,但是處理器和編譯器對整體的運算結果是有保證的。

(2)只有在時序要求嚴格的情況下需要顯式調用同步指令,具體情況如下:①在操作某些硬件寄存器或者雙口存儲器時,如果有明顯的讀寫時序要求,則應當添加同步指令,且變量需要添加volatile進行修飾。②中斷和主程序都使用同一個全局變量,在定義全局變量時增加volatile進行修飾,同時主程序在進行變量的寫操作時,需要關中斷,然后再開中斷。③在使用多線程或者多任務時共享同一個全局變量,在定義全局變量時增加volatile進行修飾,同時在進行變量的寫操作時,也需要增加信號量進行寫保護。

(3)在沒有特殊要求的情況下,不建議使用編譯器優化選項。

猜你喜歡
編譯器代碼指令
面向理想性能空間的跨架構編譯分析方法
基于 Verilog HDL 的多周期 CPU 設計與實現
《單一形狀固定循環指令G90車外圓仿真》教案設計
基于相異編譯器的安全計算機平臺交叉編譯環境設計
運行速度大突破華為《方舟編譯器》詳解
創世代碼
創世代碼
創世代碼
創世代碼
中斷與跳轉操作對指令串的影響
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合