0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

編譯器優(yōu)化教程:寄存器分配 1

jf_78858299 ? 來源:畢昇編譯 ? 作者:王博洋 ? 2023-01-30 16:15 ? 次閱讀

概念介紹

在介紹算法之前,我們回顧下基本概念:

  • |X| :X的度數(shù),(無向圖中)節(jié)點(diǎn)的鄰居個數(shù)。
  • CFG :控制流圖。
  • successor :本文指CFG中基本塊的后繼。
  • 四元式 :(op,result,arg1,arg2),比如常見的a=b+c就可以看作四元式(+,a,b,c)。
  • SSA(Static Single Assignment) :靜態(tài)單賦值。
  • use/def :舉個例子,對于指令n: c <- c+b來說 use[n]={c,b},def[n]={c}。
  • live-in :當(dāng)以下任一條件滿足時,則稱變量a在節(jié)點(diǎn)n中是live-in的,寫作a∈in[n]。節(jié)點(diǎn)n本文中代表指令。
    1. a∈use[n];
    2. 存在從節(jié)點(diǎn)n到其他節(jié)點(diǎn)的路徑使用了a且不包括a的def。
  • live-out : 變量a在節(jié)點(diǎn)n的任一后繼的live-in集合中。寫作a∈out[n]
  • 干涉 :在某一時刻,兩個變量在同一live-in集合中。
  • RIG(Register Interfere Graph) : 無向圖,其點(diǎn)集和邊集構(gòu)成如下:
  • 節(jié)點(diǎn):變量
  • 邊:如果兩節(jié)點(diǎn)存在干涉,那么這兩節(jié)點(diǎn)之間就有一條干涉邊
  • k-著色 :給定無向圖G=(V,E),其中V為頂點(diǎn)集合,E為邊集合。將V分為k個組,每組中沒有相鄰頂點(diǎn),可稱該圖G是k著色的。當(dāng)然可著色前提下,k越小越好。

需要注意的是,我們后續(xù)的算法會作用在最普通的四元式上,而不是SSA。在介紹寄存器分配算法之前,我們需要活躍變量分析來構(gòu)建干涉圖。

活躍變量分析與圖著色算法

活躍變量分析

簡單來說,就是計算每個點(diǎn)上有哪些變量被使用。

算法描述如下[1]:

input: CFG = (N, E, Entry, Exit)
begin
// init
for each basic block B in CFG
	in[B] = ?
// iterate
do{
	for each basic block B other than Exit{
		out[B] = ∪(in[s]),for all successors s of B
		in[B] = use[B]∪(out[B]-def[B])
	}
}until all in[] do't change

活躍變量分析還有孿生兄弟叫Reaching Definitions,不過實(shí)現(xiàn)功能類似,不再贅述。

舉個例子:對圖1的代碼進(jìn)行活躍變量分析

圖片

圖1[2]

可以得到每個點(diǎn)的活躍變量如圖2所示:

圖片

圖2

過程呢?限于篇幅,僅僅計算第一輪指令1的結(jié)果,剩余部分讀者可自行計算。

步驟 下標(biāo) out in
第一次迭代 1 {} {b,c}
... ... ... ...

可畫出RIG如圖3:

圖片

圖3

圖著色

經(jīng)過上文的活躍變量分析,我們得到了干涉圖,下一步對其進(jìn)行上色。

但是圖著色是一個NP問題,我們會采用啟發(fā)式算法對干涉圖進(jìn)行著色?;舅悸肥牵?/p>

  1. 找到度小于k的節(jié)點(diǎn);
  2. 從圖中刪除;
  3. 判斷是否為可著色的圖;
  4. 迭代運(yùn)行前3步直到著色完成。

算法描述[3]:

input: RIG, k
// init
stack = {}
// iterate
while RIG != {} {
	t := pick a node with fewer than k neighbors from RIG // 這里RIG可以先按度數(shù)排序節(jié)點(diǎn)再返回
	stack.push(t)
	RIG.remove(t)
}
// coloring
while stack != {} {
	t := stack.pop()
	t.color = a color different from t's assigned colored neighbors
}

對于例子1,假設(shè)有4個寄存器r1、r2、r3、r4可供分配。

步驟 stack RIG
0 {} 1675066141(1).png
1 {a} 1675066164(1).png
2 {d,a} 1675066191(1).png

所以圖3中的RIG是4-著色的。但如果只有三種顏色可用,怎么辦呢?

沒關(guān)系,我們還有大容量的內(nèi)存,雖然速度慢了那么一點(diǎn)點(diǎn)。著色失敗就把變量放在內(nèi)存里,用的時候再取出來。

依然是上例,但是k=3,只有三個顏色。

如果f的鄰居是2-著色的就好了,但不是。那就只能選一個變量存入內(nèi)存了。這里我們選擇將變量f溢出至內(nèi)存。溢出后的IR和RIG如圖:

圖片

圖4 溢出后的IR

圖片

圖5 溢出后的RIG

所以,溢出其實(shí)是分割了變量的生命周期以降低被溢出節(jié)點(diǎn)的鄰居數(shù)量。溢出后的著色圖如圖6:

圖片

圖6 著色后的圖5

這里溢出變量f并不是明智的選擇,關(guān)于如何優(yōu)化溢出變量讀者可自行查閱資料。

至此,圖著色算法基本介紹完畢。不過,如果代碼中的復(fù)制指令,應(yīng)該怎么處理呢?

寄存器分配之前會有Copy Propagation和Dead Code Elimination優(yōu)化掉部分復(fù)制指令,但是兩者并不是全能的。

比如:代碼段1中,我們可以合并Y和X。但是代碼段2中Copy Propagation就無能為力了,因?yàn)榉种?dǎo)致不同的Y值。

// 代碼段1
X = ...
A = 10
Y = X
Z = Y + A
return Z

// 代碼段2
X= A + B
Y = C
if (...) {Y = X}
Z = Y + 4

所以,寄存器分配算法也需要對復(fù)制指令進(jìn)行處理。如何處理?給復(fù)制指令的源和目標(biāo)分配同一寄存器。

那么如何在RIG中表示呢?如果把復(fù)制指令的源和目標(biāo)看作 RIG中相同的節(jié)點(diǎn) ,自然會分配同一寄存器。

  • 相同節(jié)點(diǎn)?可以擴(kuò)展RIG:新增虛線邊,代表合并候選人。
  • 成為合并候選人的條件是:如果X和Y的生命周期不重合,那么對于Y=X指令中的X和Y是可合并的。
  • 為了保證合并合法且不造成溢出:合并后局部的度數(shù)

那么如何計算局部的度數(shù)?介紹三種算法:

  • 簡單算法
  • Brigg's 算法
  • George's 算法
  1. 簡單算法:(|X|+|Y|),很保守的算法但是可能會錯過一些場景
    比如k=2時,圖7應(yīng)用簡單算法是沒辦法合并的
    圖片
    圖7[3]
    但明顯圖7可以合并成圖8:
    圖片
    圖8[3]
  2. Brigg's 算法:X和Y可合并,如果X和Y中度數(shù)≥k的鄰居個數(shù)<k。但是如果X的度數(shù)很大,算法效率就不高
  3. George's算法:X和Y可合并,如果對Y的每個鄰居T,|T| ?比如k=2時,圖9就可以合并X和Y。
    圖片
    圖9[3]
    相對于Brigg算法、George算法不用遍歷節(jié)點(diǎn)的鄰居。注意,圖著色時可以按節(jié)點(diǎn)度數(shù)從小到大依次訪問。

到此,圖著色算法介紹完畢。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5301

    瀏覽量

    119863
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1617

    瀏覽量

    49019
  • CFG
    CFG
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    9794
收藏 人收藏

    評論

    相關(guān)推薦

    編譯器優(yōu)化導(dǎo)致USART波特率配置錯誤,請問這是為什么?如何解決?

    菜鳥一枚,遇到問題上網(wǎng)找不到答案,只好自己嘗試,請大神指教。 問題描述:配置USART的波特率為38400,結(jié)果無法成功接收數(shù)據(jù),檢查后發(fā)現(xiàn)波特率配置寄存器BRR錯誤, 編譯器優(yōu)化導(dǎo)致USART
    發(fā)表于 07-06 03:05

    編譯器優(yōu)化那些事兒(5):寄存器分配

    。至此,圖著色算法基本介紹完畢。不過,如果代碼中的復(fù)制指令,應(yīng)該怎么處理呢?寄存器分配之前會有Copy Propagation和Dead Code Elimination優(yōu)化掉部分復(fù)制指令,但是兩者
    發(fā)表于 08-24 14:41

    編譯器優(yōu)化的靜態(tài)調(diào)度介紹

    約束條件進(jìn)行聯(lián)合求解得到的解決方案是相對更優(yōu)的,但由于無論是指令調(diào)度還是寄存器分配,都是很復(fù)雜的NP完全問題,綜合考慮下,編譯器一般會分別處理二者?! ≡贚LVM編譯器的設(shè)計中,
    發(fā)表于 03-17 17:07

    SIMD計算機(jī)的優(yōu)化編譯器設(shè)計

    利用處理的相關(guān)資源,提高編譯器優(yōu)化性能和增強(qiáng)代碼可適應(yīng)性是SIMD處理優(yōu)化編譯的關(guān)鍵。該文基
    發(fā)表于 04-03 08:47 ?30次下載

    寄存器組網(wǎng)絡(luò)處理上的寄存器分配技術(shù)

    本內(nèi)容提供了多寄存器組網(wǎng)絡(luò)處理上的寄存器分配技術(shù)
    發(fā)表于 06-28 15:26 ?28次下載
    多<b class='flag-5'>寄存器</b>組網(wǎng)絡(luò)處理<b class='flag-5'>器</b>上的<b class='flag-5'>寄存器</b><b class='flag-5'>分配</b>技術(shù)

    編譯器_keil的優(yōu)化選項(xiàng)問題

    keil編譯器優(yōu)化選項(xiàng)針對ARM,對STM32編譯的一些優(yōu)化的問題
    發(fā)表于 02-25 14:18 ?3次下載

    高效的C編程之寄存器分配

    14.7 寄存器分配 編譯器一項(xiàng)很重要的優(yōu)化功能就是對寄存器分配。與
    發(fā)表于 10-17 17:17 ?4次下載

    C編譯器及其優(yōu)化

    本章將幫助讀者在ARM處理上編寫高效的C代碼。本章涉及的一些技術(shù)不僅適用于ARM處理,也適用于其他RISC處理。本章首先從ARM編譯器及其優(yōu)化
    發(fā)表于 10-17 17:22 ?2次下載

    靜態(tài)變量、自動變量與寄存器變量的存儲

    register限定詞通知編譯器--程序中的變量將頻繁使用。它的意思是建議編譯器將程序中用register限定的變量放置在計算機(jī)的內(nèi)部寄存其中,這樣可能得到更小更快的程序。但是,編譯器
    發(fā)表于 06-03 11:27 ?3059次閱讀
    靜態(tài)變量、自動變量與<b class='flag-5'>寄存器</b>變量的存儲

    編譯器優(yōu)化對函數(shù)的影響

    編譯器如gcc,可以指定不同的優(yōu)化參數(shù),在某些條件下,有些函數(shù)可能會被優(yōu)化掉。
    的頭像 發(fā)表于 06-22 14:58 ?2792次閱讀
    <b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b>對函數(shù)的影響

    基于C++編譯器的節(jié)點(diǎn)融合優(yōu)化方法

    節(jié)點(diǎn),減少諸如指令、寄存器、時鐘周期和訪存等開銷,以達(dá)到減少程序運(yùn)行時間,提升訪存效率等目的。為了提升LLVM編譯器的性能,文中在LLVM編譯流程的中間表示階段和DAG合并階段、指令選擇階段提岀了節(jié)點(diǎn)融合
    發(fā)表于 06-15 14:29 ?19次下載

    什么是編譯器算法之寄存器分配

    寄存器是CPU中的稀有資源,如何高效的分配這一資源是一個至關(guān)重要的問題。本文介紹了基于圖著色的寄存器分配算法。
    的頭像 發(fā)表于 03-02 16:11 ?1055次閱讀
    什么是<b class='flag-5'>編譯器</b>算法之<b class='flag-5'>寄存器</b><b class='flag-5'>分配</b>

    怎么給D寄存器輸入數(shù)值 三菱plc寄存器D怎么讀取

    在單片機(jī)編程中,給D寄存器輸入數(shù)值的方法取決于所使用的編程語言和編譯器
    發(fā)表于 04-12 13:33 ?1.6w次閱讀

    編譯器優(yōu)化選項(xiàng)

    一個程序首先要保證正確性,在保證正確性的基礎(chǔ)上,性能也是一個重要的考量。要編寫高性能的程序,第一,必須選擇合適的算法和數(shù)據(jù)結(jié)構(gòu);第二,應(yīng)該編寫編譯器能夠有效優(yōu)化以轉(zhuǎn)換成高效可執(zhí)行代碼的源代碼,要做到
    的頭像 發(fā)表于 11-24 15:37 ?838次閱讀
    <b class='flag-5'>編譯器</b>的<b class='flag-5'>優(yōu)化</b>選項(xiàng)

    Keil編譯器優(yōu)化方法

    我們都知道,代碼是可以通過編譯器優(yōu)化的,有的時候,為了提高運(yùn)行速度或者減少代碼尺寸,會開啟優(yōu)化選項(xiàng)。
    的頭像 發(fā)表于 10-23 16:35 ?270次閱讀
    Keil<b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b>方法