你有沒有聽說過Loop Invariant Code Motion?
這是來自編譯器的優化傳遞,儘可能將代碼移出循環主體。
例如,給定下面的代碼:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
for (int i = 0; i < argc; ++i) {
if (argc < 100) {
printf("%d\n", atoi(argv[1]));
}
}
}
鏘生成以下IR:
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
%1 = icmp sgt i32 %argc, 0
br i1 %1, label %.lr.ph, label %._crit_edge
.lr.ph: ; preds = %0
%2 = icmp slt i32 %argc, 100
%3 = getelementptr inbounds i8** %argv, i64 1
br i1 %2, label %4, label %._crit_edge
; <label>:4 ; preds = %4, %.lr.ph
%i.01.us = phi i32 [ %9, %4 ], [ 0, %.lr.ph ]
%5 = load i8** %3, align 8, !tbaa !0
%6 = tail call i64 @strtol(i8* nocapture %5, i8** null, i32 10) nounwind
%7 = trunc i64 %6 to i32
%8 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 %7) nounwind
%9 = add nsw i32 %i.01.us, 1
%exitcond = icmp eq i32 %9, %argc
br i1 %exitcond, label %._crit_edge, label %4
._crit_edge: ; preds = %4, %.lr.ph, %0
ret i32 0
}
可以被翻譯回C:
int main(int argc, char** argv) {
if (argc == 0) { return 0; }
if (argc >= 100) { return 0; }
for (int i = 0; i < argc; ++i) {
printf("%d\n", atoi(argv[1]));
}
return 0;
}
結論:不打擾微觀優化,除非一個剖析器顯示它們不像您想象的那麼微小。
編輯:
編輯從根本上改變這個問題(上帝,我恨:P)。LICM不再適用,兩種功能的功能差別很大。
但結論仍然相同。 for
循環中的單個if
檢查不會改變代碼的基本複雜性(請記住,循環條件也在每次迭代中都進行測試...)。
我會用後者,但爲什麼不只是運行這兩個版本,看看哪一個更快? –
我猜你已經簡化了你的代碼,但是如你所寫的,你可以在循環之外移動'if(bState)'測試。 – Chowlett
一如既往,答案是:如果你真的關心,*簡介*。可能不會有明顯的差異 - 但這只是我個人的預測。同樣,只有分析才能說明。 – delnan