色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

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

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

冬至子 ? 來(lái)源:畢昇編譯 ? 作者:王博洋 ? 2023-05-24 16:05 ? 次閱讀

概念介紹

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

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

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

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

活躍變量分析

簡(jiǎn)單來(lái)說(shuō),就是計(jì)算每個(gè)點(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,不過(guò)實(shí)現(xiàn)功能類似,不再贅述。

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

image.png

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

image.png

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

image.png

可畫出RIG如圖3:

image.png

圖著色

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

但是圖著色是一個(gè)NP問題,我們會(huì)采用啟發(fā)式算法對(duì)干涉圖進(jìn)行著色。基本思路是:

  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  
}`

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

image.png

寄存器分配

image.png

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

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

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

image.png

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

image.png

image.png

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

image.png

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

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

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

比如:代碼段1中,我們可以合并Y和X。但是代碼段2中Copy Propagation就無(wú)能為力了,因?yàn)榉种?huì)導(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`

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

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

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

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

  • 簡(jiǎn)單算法
  • Brigg's 算法
  • George's 算法
  1. 簡(jiǎn)單算法:(|X|+|Y|),很保守的算法但是可能會(huì)錯(cuò)過(guò)一些場(chǎng)景
    比如k=2時(shí),圖7應(yīng)用簡(jiǎn)單算法是沒辦法合并的

`

image.png

7\\[3\\]

但明顯圖7可以合并成圖8:

image.png

8\\[3\\]
  1. Brigg's 算法:X和Y可合并,如果X和Y中度數(shù)≥k的鄰居個(gè)數(shù)<k。但是如果X的度數(shù)很大,算法效率就不高

  2. George's算法:X和Y可合并,如果對(duì)Y的每個(gè)鄰居T,|T| ?比如k=2時(shí),圖9就可以合并X和Y。或者t和x沖突。

image.png

相對(duì)于Brigg算法、George算法不用遍歷節(jié)點(diǎn)的鄰居。注意,圖著色時(shí)可以按節(jié)點(diǎn)度數(shù)從小到大依次訪問。

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

線性掃描

接下來(lái)介紹一種不同思路的算法:線性掃描。算法描述如下[4]:

`LinearScanRegisterAllocation:  
    active := {}  
    for i in live interval in order of increasing start point  
        ExpireOldIntervals(i)  
        if length(avtive) == R  
            SpillAtInterval(i)  
        else  
            register[i] := a regsiter removed from pool of free registers  
            add i to active, sorted by increasing end point  
ExpireOldInterval(i)  
    for interval j in active, in order of increaing end point  
        if endpoint[j] >= startpoint[i]  
            return  
        remove j from active  
        add register[j] to pool of free registers  
SpillAtInterval(i)  
    spill := last interval in active  
    if endpoint[spill] > endpoint[i]  
        register[i] := register[spill]  
        location[spill] := new stack location  
        remove spill from active  
        add i to active, sorted by increasing end point  
    else  
        location[i] := new stack location`

live interval其實(shí)就是變量的生命期,用活躍變量分析可以算出來(lái)。不過(guò)需要標(biāo)識(shí)第一次出現(xiàn)和最后一次出現(xiàn)的時(shí)間點(diǎn)。

舉個(gè)例子:

image.png

image.png

llvm中實(shí)現(xiàn)

在上文中介紹的算法都是作用在最普通的四元式上,但LLVM-IR是SSA形式,有PHI節(jié)點(diǎn),但PHI節(jié)點(diǎn)沒有機(jī)器指令表示,所以在寄存器分配前需要把PHI節(jié)點(diǎn)干掉,消除PHI節(jié)點(diǎn)的算法限于篇幅不展開,如感興趣的話請(qǐng)后臺(tái)留言。

llvm作為工業(yè)級(jí)編譯器,有多種分配算法,可以通過(guò)llc的命令行選項(xiàng)-regalloc=pbqp|greedy|basic|fast來(lái)手動(dòng)控制分配算法。

不同優(yōu)化等級(jí)默認(rèn)使用算法也不同:O2和O3默認(rèn)使用greedy,其他默認(rèn)使用fast。

fast算法的策略很簡(jiǎn)單,掃描代碼并為出現(xiàn)的變量分配寄存器,寄存器不夠用就溢出到內(nèi)存。用途主要是 調(diào)試

basic算法以linearscan為基礎(chǔ)并對(duì)life interval設(shè)置了溢出權(quán)重而且用優(yōu)先隊(duì)列來(lái)存儲(chǔ)life interval。

greedy算法也使用優(yōu)先隊(duì)列,但特點(diǎn)是先為生命期長(zhǎng)的變量分配寄存器,而短生命期的變量可以放在間隙中,詳情可以參考[5]。

pbqp算法全稱是Partitioned Boolean Quadratic Programming,限于篇幅,感興趣的讀者請(qǐng)查閱[6]。

至于具體實(shí)現(xiàn),自頂向下依次是:

  • TargetPassConfig::addMachinePasses含有寄存器分配和其他優(yōu)化

  • addOptimizedRegAlloc中是與寄存器分配密切相關(guān)的pass,比如上文提到的消除PHI節(jié)點(diǎn)

  • addRegAssignAndRewriteOptimized是實(shí)際的寄存器分配算法

  • 寄存器分配相關(guān)文件在lib/CodeGen下的RegAllocBase.cpp、RegAllocGreedy.cpp、RegAllocFast.cpp、RegAllocBasic.cpp和RegAllocPBQP.cpp等。

  • RegAllocBase類定義了一系列接口,重點(diǎn)是selectOrSplit和enqueue/dequeue方法,數(shù)據(jù)結(jié)構(gòu)的重點(diǎn)是priority queue。selectOrSplit方法可以類比上文中提到的SpillAtInterval。priority queue類比active list。簡(jiǎn)要代碼如下:

void RegAllocBase::allocatePhysRegs() {  // 1. virtual reg其實(shí)就是變量  while (LiveInterval *VirtReg = dequeue()) {    // 2.selectOrSplit 會(huì)返回一個(gè)可用的物理寄存器然后返回新的live intervals列表    using VirtRegVec = SmallVector4>;    VirtRegVec SplitVRegs;    MCRegister AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs); // 3.分配失敗檢查    if (AvailablePhysReg == ~0u) {     ...    } // 4.正式分配    if (AvailablePhysReg)      Matrix->assign(*VirtReg, AvailablePhysReg);     for (Register Reg : SplitVRegs) {      // 5.入隊(duì)分割后的liver interval      LiveInterval *SplitVirtReg = &LIS->getInterval(Reg);      enqueue(SplitVirtReg);    }  }}
,>

至于這四種算法的性能對(duì)比,我們主要考慮三個(gè)指標(biāo):運(yùn)行時(shí)間、編譯時(shí)間和溢出次數(shù)。

image.png

橫坐標(biāo)是測(cè)試集,縱坐標(biāo)是以秒為單位的運(yùn)行時(shí)間

image.png

橫坐標(biāo)是測(cè)試集,縱坐標(biāo)是編譯時(shí)間

image.png

從這三幅圖可以看出greedy算法在大多數(shù)測(cè)試集上都優(yōu)于其他算法,因此greedy作為默認(rèn)分配器是可行的。

小結(jié)

我們通過(guò)一個(gè)例子介紹了活躍變量分析和圖著色算法。借助活躍變量分析,我們知道了變量的生命期,有了變量生命期建立干涉圖,對(duì)干涉圖進(jìn)行著色。如果著色失敗,可以選擇某個(gè)變量溢出到內(nèi)存中。之后在RIG的基礎(chǔ)上介紹了寄存器合并這一變換。

然后我們簡(jiǎn)單介紹了不同思路的寄存器分配算法:linearscan。最后介紹了llvm12中算法的實(shí)現(xiàn)并對(duì)比了llvm中四種算法的性能差異。

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

    關(guān)注

    31

    文章

    5363

    瀏覽量

    120960
  • SSA
    SSA
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    2975
收藏 人收藏

    評(píng)論

    相關(guān)推薦

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

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

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

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

    寄存器組網(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)針對(duì)ARM,對(duì)STM32編譯的一些優(yōu)化的問題
    發(fā)表于 02-25 14:18 ?3次下載

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

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

    靜態(tài)變量、自動(dòng)變量與寄存器變量的存儲(chǔ)

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

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

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

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

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

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

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

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

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

    編譯器優(yōu)化那些事兒:別名分析概述

    別名分析是編譯器理論中的一種技術(shù),用于確定存儲(chǔ)位置是否可以以多種方式訪問。如果兩個(gè)指針指向相同的位置,則稱這兩個(gè)指針為別名。
    的頭像 發(fā)表于 05-24 16:16 ?597次閱讀
    <b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b><b class='flag-5'>那些</b><b class='flag-5'>事兒</b>:別名分析概述

    編譯器優(yōu)化那些事兒之區(qū)域分析

    為了有效地優(yōu)化代碼,編譯器需要在程序的各個(gè)節(jié)點(diǎn)建立并求解與信息有關(guān)的方程來(lái)收集數(shù)據(jù)流信息,并將這些信息分發(fā)給流程圖的每個(gè)塊,這個(gè)過(guò)程被稱為數(shù)據(jù)流分析。
    的頭像 發(fā)表于 06-07 11:36 ?867次閱讀
    <b class='flag-5'>編譯器</b><b class='flag-5'>優(yōu)化</b><b class='flag-5'>那些</b><b class='flag-5'>事兒</b>之區(qū)域分析

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

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

    Triton編譯器與其他編譯器的比較

    Triton編譯器與其他編譯器的比較主要體現(xiàn)在以下幾個(gè)方面: 一、定位與目標(biāo) Triton編譯器 : 定位:專注于深度學(xué)習(xí)中最核心、最耗時(shí)的張量運(yùn)算的優(yōu)化。 目標(biāo):提供一個(gè)高度抽象、靈
    的頭像 發(fā)表于 12-24 17:25 ?455次閱讀

    Triton編譯器優(yōu)化技巧

    在現(xiàn)代計(jì)算環(huán)境中,編譯器的性能對(duì)于軟件的運(yùn)行效率至關(guān)重要。Triton 編譯器作為一個(gè)先進(jìn)的編譯器框架,提供了一系列的優(yōu)化技術(shù),以確保生成的代碼既高效又適應(yīng)不同的硬件架構(gòu)。 1. 指令
    的頭像 發(fā)表于 12-25 09:09 ?319次閱讀
    主站蜘蛛池模板: 在线免费观看毛片 | 姑娘视频日本在线播放 | 被公疯狂玩弄的漂亮人妻 | 把腿张开再深点好爽宝贝动态图 | 超大BBWWW| 欧美白妞大战非洲大炮 | 和搜子的日子 在线观看 | Chinesetube国产中文 | 永久adc视频 | 国内精品久久久久影院男同志 | 肉动漫无修在线播放 | 亚洲精品无码久久久久A片空 | 一个人的免费完整在线观看HD | 动漫成年美女黄漫网站 | 国产全肉乱妇杂乱视频 | 亚洲色无码播放 | 欧美极限变态扩张video | 久久精品成人免费看 | 韩国三级久久精品 | 爽爽影院免费观看 | 午夜DY888国产精品影院 | 高清日本片免费观看 | 亚洲AV國產国产久青草 | 妺妺窝人体色777777野大粗 | 日本高清在线一区二区三区 | 久久亚洲精品无码A片大香大香 | 国产精品AV无码免费播放 | 久久精品国产免费播高清无卡 | 国产在线高清亚洲精品一区 | 久久4k岛国高清一区二区 | 欧美精品XXXXBBBB| 99国产在线视频有精品视频 | 99视频在线精品免费观看18 | 大乳牛奶女magnet | 亚洲欧美日韩综合影院 | 欧美在线看欧美视频免费 | 国产色婷亚洲99精品AV | 97在线视频网站 | 国产小视频在线高清播放 | 蜜芽TV影院在线视频 | 欧美精品3atv一区二区三区 |