爲什麼gcc編譯器在創建彙編代碼時將while循環轉換爲do-while構造?我知道任何while循環,可以在Cgcc循環構造修改爲彙編代碼
while (test) { ... }
可以寫成一個做,而例如可以改寫爲
if (!test) goto skip;
do {
. . .
} while (test);
skip:
爲什麼gcc編譯器在創建彙編代碼時將while循環轉換爲do-while構造?我知道任何while循環,可以在Cgcc循環構造修改爲彙編代碼
while (test) { ... }
可以寫成一個做,而例如可以改寫爲
if (!test) goto skip;
do {
. . .
} while (test);
skip:
大廈,你可能不知道爲什麼 do-while構造更高效,特別是考慮到如圖所示,測試已被複制(因此生成的代碼更大)。答案是很經常的測試表現總是能夠證明是在循環入口真,所以
if (!test) goto skip;
loop:
. . . // loop body
if (!test) goto loop;
skip:
. . . // continue the program
可以簡化爲
loop:
. . . // loop body
if (!test) goto loop;
. . . // continue program
現在,爲什麼不這樣做,在同一時間原始轉換,並避免原始轉換,如果編譯器不能證明循環會至少循環一次?因爲證明循環的算法至少循環一次實際上是一個通用的if-condition優化器。優化的通常順序是這樣的:
另一件需要知道的事情是,有時會因爲編譯器期望產生更好的運行時行爲而故意留下重複的測試。例如,如果編譯器有理由相信循環很多次循環,但不能證明它至少循環了一次,那麼循環上方的條件分支指令幾乎總是通過,並且循環下的條件分支幾乎總是跳轉。在這種情況下,將它們分開可能會使CPU的分支預測器更加準確。分支預測精度僅次於緩存友好性,因爲它是現代無序CPU速度的限制因素。
在一般do-while
環比while
循環更有效。由於編譯器想要創建一個快速(而不是可讀)的程序,因此它將大多數while
循環轉換爲do-while
循環。
事實上,如果採用只if
和goto
(接近彙編語言)一while
循環可以做如下:
start:
if (!test) goto skip;
. . . // loop body
goto start;
skip:
; // continue the program
這是等效的,但是可能比do-while
執行效率較低(因爲後者有代碼迴路內小1線):上anatolyg的答案
if (!test) goto skip;
loop:
. . . // loop body
if (!test) goto loop;
skip:
; // continue the program
因爲在彙編語言中沒有'for'或'while'循環。 –
如果您想討論Assembly,請發佈編譯器生成的彙編代碼。 –