2014-11-06 77 views
71

是否有可能有一個環,其具有零執行時間?我認爲即使是空循環也應該有一個執行時間,因爲它有一個相關的開銷。循環以零執行時間

+37

循環可能會被展開和/或由編譯器完全消除。 – 2014-11-06 04:24:54

+4

優化編譯器的主要工作之一是數據流分析。生成不會在任何地方流動的數據的計算被消除,包括循環。確切的行爲取決於你的編譯器。 – 2014-11-06 04:29:49

+0

這實際上同樣適用於C++,我也會將相關的C++引用添加到我的答案中。 – 2014-11-06 14:54:13

回答

52

是 - 如果編譯器確定循環是死代碼(永遠不會執行),那麼它將不會生成代碼。該循環將有0個執行時間,但嚴格來說,它不存在於機器代碼級別。

119

是,根據爲,如果規則編譯器只是有義務模擬代碼的可觀察的行爲,所以如果你有一個循環,沒有任何可觀察到的行爲,那麼它可以完全,因此優化掉將有效地執行零時間。

實例

例如以下代碼:

int main() 
{ 
    int j = 0 ; 
    for(int i = 0; i < 10000; ++i) 
    { 
    ++j ; 
    } 
} 

使用所述-O3標誌gcc 4.9編譯基本上最終減少到以下(see it live):

main: 
    xorl %eax, %eax # 
    ret 

幾乎所有的優化都被允許在之下,因爲如果規則爲,我知道的唯一例外是copy elison,它允許影響可觀察行爲。

其他一些例子包括dead code elimination,它可以刪除編譯器可以證明永遠不會執行的代碼。例如,即使下面的循環確實含有副作用,可以優化掉了,因爲我們可以證明這一點永遠不會被執行(see it live):

#include <stdio.h> 

int main() 
{ 
    int j = 0 ; 
    if(false) // The loop will never execute 
    { 
    for(int i = 0; i < 10000; ++i) 
    { 
     printf("%d\n", j) ; 
     ++j ; 
    } 
    } 
} 

循環將優化掉同前例。一個更有趣的例子就是,在一個循環的計算可以推斷爲一個常數,從而避免爲一個循環需要的情況下(不知道優化類別,這屬於下),例如:

int j = 0 ; 
for(int i = 0; i < 10000; ++i) 
{ 
    ++j ; 
} 
printf("%d\n", j) ; 

可以被優化掉,以(see it live):

movl $10000, %esi #, 
movl $.LC0, %edi #, 
xorl %eax, %eax # 
call printf # 

我們可以看到有沒有參與循環。

凡作爲,如果規則覆蓋標準

爲,如果規則是覆蓋在其中說,草案C99標準節5.1.2.3程序執行

在抽象機器,所有表達式都按照 指定的語義進行評估。一個實際的實現不需要評估 表達式的一部分,如果它可以推斷出它的值沒有被使用,並且沒有產生任何需要的副作用(包括由調用 函數或訪問一個易失性對象引起的任何副作用)。

as-if rule也適用於C++,gcc也會在C++模式下產生相同的結果。 C++標準草案包括在本節1.9程序執行

在本國際標準的語義描述限定 參數化非確定性抽象機。該國際標準沒有要求符合 實施的結構。尤其是,他們不需要複製或模擬抽象機器的結構。相反,符合實現 需要(僅)模擬抽象 機的可觀察行爲所解釋below.5

+0

我敢打賭,即使不是所有的語言規範都有一個_as-if_規則,大部分都是如此。如果不使用並且沒有副作用,那麼通常沒有必要進行計算。它只會浪費時間和精力。 – 2014-11-06 21:57:19

+15

@CraigAnderson:絕大多數時候都是這樣,但是有很少的情況你會做無用的計算,比如在你希望所有代碼路徑花費相同時間的加密操作中防止[定時通道攻擊](http://en.wikipedia.org/wiki/Timing_attack)。 – 2014-11-06 22:14:40

+0

**換句話說**:對於執行實際的,不可避免的,不可作弊的工作的實際循環,答案是:**否**。對於只能做多餘的東西的僞循環:**是**。 – 2015-02-01 15:29:54

3

編譯器沒有義務評估沒有副作用並且結果被丟棄的表達式或表達式的一部分。

哈比森和Steele,C: A Reference Manual