基本塊和流圖
•採用圖的方式表示中間代碼,有助於生成更好的代碼
ä構造方法
1.把中間代碼劃分成基本塊(basic block,BB),每個基本塊滿足如下條件:
①控制流只能從基本塊的第一個指令進入
②除了基本塊的最後一條指令,控制流在離開基本塊前不會停機或者跳轉
2.基本塊形成了流圖(flow graph)的結點,流圖的邊指明瞭哪些基本塊可能緊隨一個基本塊之後執行
ä中斷等程序行爲可能打破基本塊的上述約定1
•構造基本塊和流圖的目的是對代碼進行優化
ä如果中斷正常返回,則中斷本身的保護機制可以使程序正常執行下去,不影響正確性,但可能形象優化效果
ä如果中斷導致異常退出,優化的結果也不會有錯,程序本身非正常終止
基本塊(1)
•基本塊:
ä定義:基本塊是程序中最大限度順序執行的語句序列,其中只有一個入口和出口,入口是其第一個語句,出口是其最後一個語句
ä基本塊的入口語句可能是
•程序的第一個語句
•跳轉的目標語句
•條件跳轉的下一條語句
ä基本塊的結束語句可能是
•停機語句
•跳轉語句
•跳轉目標語句的前一個語句(詞法序)
•基本塊(續)
ä構造方法
•輸入:一個三地址指令序列
•輸出:與之對應的基本塊列表,每個指令恰好被分到一個基本塊中
•方法:
ä首先,取定中間代碼序列中哪些指令是首指令(leader,入口指令,基本塊的第一條指令)
1.中間代碼的第一個三地址指令是一個首指令
2.任意一個條件或無條件轉移指令的目標指令是一個首指令
3.緊跟在一個條件或無條件轉移指令之後的指令是一個首指令
ä然後,每個首指令對應的基本塊包括了從它自己開始,直到下一個首指令(不含)或者中間程序的結尾指令之間的所有指令
ä一個特殊情況:過程調用語句作爲一個新的基本塊的開始,甚至獨立成爲一個基本塊
後續使用信息
•下次不再引用意味着優化的機會
ä寄存器優化
ä臨時名字存儲單元的指派
•計算後續使用信息
ä三地址語句中名字的使用(use)定義:
•假定三地址語句i把a的值賦給x,如果語句j用x作爲運算對象,並且控制從i流到j,這條路徑中沒有x的其它賦值,則稱j引用x在i定的值
•此時,稱x在語句i處活躍(live)
ä在基本塊內:後續使用信息
•對每個基本塊反向掃描
•爲每個名字x在符號表中登記它是否在本塊中有後續使用
•如果在本塊中沒有後續使用,則登記它是否在本塊的出口活躍。缺省認爲所有的非臨時變量在出口都是活躍的
ä算法8.7:對一個基本塊中的每一個語句確定活躍性與後續使用信息
•輸入:一個三地址語句的基本塊B,假設在基本塊B開始時,所有的非臨時變量都是活躍的
•輸出:對於每一個語句i:x = y op z,將x、y及z的活躍性信息及後續使用信息關聯到i
•方法:從基本塊B的最後一個語句開始,反向掃描到B的開始處。對每一個三地址語句 i:x := y op z,依次執行下述步驟:
ä把當前符號表中x、y和z的後續使用信息和活躍信息附加到語句i上;(若x不活躍,則這個語句可以刪掉)
ä在符號表中設置x爲“無後續使用”和“不活躍”;
ä把符號表中y和z的後續使用信息均置爲i,活躍信息均置爲“活躍”。
注意:上述次序不能顛倒,因爲x可能是y或z
流圖(1)
•定義:控制流圖或流圖
ä結點是基本塊的有向圖G = ( N, E, root)
•N是結點的集合,每個結點表示一個基本塊
•E是邊的集合,如果結點ni和nj間存在前驅和後繼的關係,則在存在一條從ni到nj的有向邊(此時意味着,在ni執行後,可能會執行nj)
äni的出口語句是goto(s)或if … goto(s),且(s)是的nj入口語句
änj在程序中的位置緊跟在ni後,且ni的出口語句不是無條件轉移語句和停語句
•root是流圖的首結點(或稱爲根結點),是包含程序第一個語句的基本塊
ä每個流圖都可以等價變換爲單入口,且每個結點最多有兩個後繼的圖
流圖的表示方式
•可以用任意的表示圖的數據結構表示流圖
•結點(基本塊)
ä基本塊是一個指令序列
ä可能要頻繁改變這個指令序列
•數量或組成的指令
•目的之一是優化
ä採用指令鏈表的形式較爲高效