1 簡述數據流分析
數據流(dataflow)分析將程序看成數據和數據的流動轉移,而將轉移的控制條件忽略掉,只關注數據在轉移過程中的變化。
例如,對於上一節的停機問題的反例程序:
void Evil() {
if(Halt(Evil)==False)
return;
else
while(True);
}
其中的if-else
就是控制條件,將它忽略掉,抽象成一對非確定選擇(即在這裏程序隨機選擇一條路走)向左走向右走:
void Evil() {
向左走 return;
向右走 while(True);
}
即使沒有了if-else
,停機問題的反例程序還可以單純用循環給出:
void Evil() {
while(Halt(Evil))
;
}
這裏的循環條件也屬於控制條件,將它也抽象成非確定選擇:
void Evil() {
AGAIN:
向左走 goto AGAIN;
向右走 return;
}
像這樣將原始程序中的控制條件都抽象成非確定選擇,忽略程序的條件判斷,認爲所有分支都可能到達,就得到了抽象程序。原始程序只有一條執行路徑,抽象程序上有多條執行路徑。原始程序的執行路徑一定包含在抽象程序的執行路徑中,所以對原始程序的問題判定可以轉換成對抽象程序的判定。
如對停機問題,原始程序上要求存在自然數n,使程序執行路徑長小於n。而對於抽象程序,是存在自然數n,使程序所有路徑長度都小於n。
注意,抽象程序上的判定問題,得到的是上/下近似的解而不是確定解。如對停機問題而言,實際上就是將抽象程序繪製成流程圖,如果流程圖中沒有環,那麼可以說原始程序一定停機;如果流程圖中有環,那麼要返回[不知道],因爲不存在自然數n使得所有路徑長度都小於n(抽象程序的流程圖中已經沒有條件控制了,環路長度就是無窮)。
2 例:符號分析
符號判定問題的數據流分析。
2.1 簡述
回顧筆記1中第6部分的符號判定問題。對於給定的程序,去掉分支判斷和條件循環之後,得到的抽象程序會有很多分支。使用抽象符號域上作運算的方法,引入[不知道],在個不同的分支上分別得到結果,最終判定的輸出就是:
如果和一樣,非確定選擇合併的結果就是,否則結果就是[不知道]。
爲了減少計算量,不必在每條路徑結尾做合併,可以在控制流結束匯合的地方提前合併,再將合併結果向下運算,如對於:
xxx
if(xxx)
xxx
else
xxx
while(xxx)
xxx
xxx
xxx
...
那麼只要在while
循環結束的地方(即是控制流匯合的地方)提前合併即可。
2.2 算法過程
這裏直接貼老師PPT:
3 例:活躍變量分析
活躍變量判定問題的數據流分析。
3.1 簡述
給出程序中的變量和程序點,如果會在從出發的某條路徑上使用,那麼對於點而言就是活躍變量,否則就不是。活躍變量的分析可以用來做寄存器的換出,對於不活躍的變量沒必要再佔用寄存器資源。
3.2 算法過程
逆向計算路徑上的活躍變量,見這篇文章。
PPT上講的沒看懂:
4 半格和偏序
4.1 半格(Semilattice)
半格是二元組,其中是一個集合,是一個交匯運算(也就是集合中若干元素經過這個運算會聚合成一個)。要求對中的任意元素,在運算上是冪等、交換、結合的,而且中要存在一個最大元(或者叫頂元素)使得任意有。
例如,正整數集合上的"求最小公倍數"的運算就是一個半格,其中最大元。
半格的笛卡爾積還是半格:
4.2 偏序(Partial Order)
偏序是二元組,其中是一個集合,是一個二元關係,要求這個二元關係是自反、傳遞、反對稱的。
例如,實數集合上的小於等於關係就是一個偏序關係。
4.3 半格和偏序的關係
每個半格都定義了同一集合上的一個偏序關係,具體是:
例如,正整數集合上的"求最小公倍數運算"是半格,而"整除關係"是對應的偏序。
又如,任意集合和"交集操作"組成了一個半格,頂元素是全集,而"子集關係"是對應的偏序。
又如,任意集合和"並集操作"組成了一個半格,頂元素是空集,而"超集關係"是對應的偏序。
4.4 半格的例子——抽象符號域的交匯操作
對於2
的符號分析,在2.2
中可以看到擴展的抽象符號域是:
那麼這個集合上的交匯操作就是一個半格了,其中最大元就是,而從:
這些交匯操作規則可以導出這個半格對應的偏序關係:
可以將這些偏序關係整合成偏序圖:
可以看到從下往上畫偏序圖的話,偏序關係對應的半格的頂元素(最大元)就是在最頂上的。
4.5 半格的高度
半格的高度是對應偏序關係的偏序圖中任意兩個結點的最大距離+1,例如4.4
抽象符號域的交匯操作的半格,高度就是3。
又如,集合和交集/並集操作組成的半格,高度是集合大小+1。
又如,活躍變量分析中,半格高度爲變量總數+1。
4.6 單調(遞增)函數
單調函數是定義在偏序關係上的。給定偏序關係,稱一個定義在上的函數是單調遞增的,當且僅當對任意有:
例如,對2
符號分析中的加減乘除操作(固定一個參數)都是單調函數。
和3
活躍變量分析有關的是, 在集合和交/並操作構成的半格中,給定任意兩個集 合,函數爲單調函數。
5 數據流分析單調框架
對於2
和3
是同一類問題,可以用數據流分析通用的框架(數據流分析單調框架)導出不同的算法。對於逆向分析,變換控制流圖方向再應用單調框架即可。
算法僞代碼: