基本介紹
- 中文名:常數摺疊
- 外文名:Constant folding
- 學科:計算機科學
- 又名:常量摺疊
- 作用:增加精確度
簡介,常數摺疊與跨平台編譯,常數傳播,最佳化的行為,
簡介
i = 320 * 200 * 32;
多數的現代編譯器不會真的產生兩個乘法的指令再將結果儲存下來,取而代之的,他們會辨識出語句的結構,並在編譯時期將數值計算出來(在這個例子,結果為2,048,000),通常會在中介碼(IR,intermediate representation)樹中進行。
有些編譯器,常數摺疊會在初期就處理完,所以像是C語言的陣列,初始化時就可以接受簡單的運算表示式。而將常數摺疊放在較後期的階段的編譯器,也相當常見。
常數摺疊與跨平台編譯
常數傳播
常數傳播是一個替代表示式中已知常數的過程,也是在編譯時期進行,包含前述所定義,內建函式也適用於常數,以下列描述為例:
int x = 14;
int y = 7 - x / 2;
return y * (28 / x + 2);
傳播x變數將會變成:
int x = 14;
int y = 7 - 14 / 2;
return y * (28 / 14 + 2);
持續傳播,則會變成:(還可以再進一步的消除無用程式碼x及y來進行最佳化)
int x = 14;
int y = 0;
return 0;
常數傳播也可能導致使狀態的分支簡化,或是變成更複雜,當狀態表示式在編譯時期可以被計算為TRUE或是FALSE時,就可以決定他唯一的一種可能。
最佳化的行為
常數摺疊及傳播通常會同時被使用在簡化以及減少,藉由交錯使用他們,一直到沒有必要再改變,舉例來說:
int a = 30;
int b = 9 - a / 5;
int c; c = b * 4;
if (c > 10) { c = c - 10; }
return c * (60 / a);
使用常數傳播,再使用常數摺疊後,產生:
int a = 30;
int b = 3; int c;
c = b * 4;
if (c > 10) { c = c - 10; }
return c * 2;
再做一次:
int a = 30;
int b = 3;
int c;
c = 12;
if (true)
{
c = 2;
}
return c * 2;
當 a 及 b 已經被簡化為常數,他們的數值取代了程式碼中任何一個使用到變數的地方,編譯器接著將會使用死碼刪除(dead code elimination)來消除他們:
int c;
if (true)
{
c = 2;
}
return c * 2;
在上述的程式,可以根據編譯器的框架來判別可以用1或是其他的布林常數來取代 True ,伴隨傳統的常數傳播,我們將得到相當多的最佳化,他無法改變程式的結構。
還有其他類似的最佳化,被稱之為稀疏有條件的常量傳播(sparse conditional constant propagation),他依據if狀態選擇了合適的分支,編譯器偵測到 if 的描述中,將永遠被賦予TRUE, c變數可以被消除,完成之後程式碼變成:
return 4;
如果這個虛擬碼為一個函式,編譯器將可將其以整數 4來取代,以消除無用的函式呼叫,改進整體的運行效能。