问题描述
我有以下循环:
//condition will be set here to true or false
for (int i = 0; i < LARGE_NUMBER; i++) {
if (condition) {
//do foo
} else {
//do bar
}
}
假设:如果没有条件,条件。 (这是真的吗?)
问题:如果,如果
条件
已设置,在循环之外,并且循环本身不触及条件
?
Assumption: A cycle if faster without a condition than with a condition. (Is this true?)Question: Will gcc factor out my
if
, if condition
has been set outside the for cycle, and the cycle itself doesn't touch condition
?
如果没有,我应该切换
如果
和代表
,重复代码,违反DRY等。
If not, I should switch the
if
and the for
, duplicate code, violate DRY, etc.
推荐答案
对于那些不想读长篇文章的人来说,这个优化被称为(在LLVM中)):
Is transformed into SSA form (via LLVM try out):
define i32 @main(i32 %argc, i8** nocapture %argv) {
entry:
%0 = icmp eq i32 %argc, 0 ; <i1> [#uses=1]
br i1 %0, label %bb5, label %bb.nph
bb.nph: ; preds = %entry
%1 = and i32 %argc, 1 ; <i32> [#uses=1]
%toBool = icmp eq i32 %1, 0 ; <i1> [#uses=1]
%2 = getelementptr inbounds i8** %argv, i64 1 ; <i8**> [#uses=1]
br i1 %toBool, label %bb3.us, label %bb3
bb3.us: ; preds = %bb3.us, %bb.nph
%i.07.us = phi i32 [ %4, %bb3.us ], [ 0, %bb.nph ] ; <i32> [#uses=1]
%3 = load i8** %argv, align 8 ; <i8*> [#uses=1]
tail call void @_Z3fooPc(i8* %3)
%4 = add nsw i32 %i.07.us, 1 ; <i32> [#uses=2]
%exitcond = icmp eq i32 %4, %argc ; <i1> [#uses=1]
br i1 %exitcond, label %bb5, label %bb3.us
bb3: ; preds = %bb3, %bb.nph
%i.07 = phi i32 [ %6, %bb3 ], [ 0, %bb.nph ] ; <i32> [#uses=1]
%5 = load i8** %2, align 8 ; <i8*> [#uses=1]
tail call void @_Z3fooPc(i8* %5)
%6 = add nsw i32 %i.07, 1 ; <i32> [#uses=2]
%exitcond8 = icmp eq i32 %6, %argc ; <i1> [#uses=1]
br i1 %exitcond8, label %bb5, label %bb3
bb5: ; preds = %bb3, %bb3.us, %entry
ret i32 0
}
也不太可读,所以让我指出这里是什么:
Not too readable perhaps, so let me point out what's here:
-
c>:检查
argc
等于0,如果是,转到bb5
bb.nph
-
bb.nph
:计算condition
,如果为真,请转到bb3.us
否则转到bb3
-
bb3.us
和bb3
假条件。 -
bb5
:exit
entry
: check ifargc
is equal to 0, if it is, go tobb5
(exit) else go tobb.nph
bb.nph
: compute the value ofcondition
, if it's true, go tobb3.us
else go tobb3
bb3.us
andbb3
: loops for the true and false condition respectivelybb5
: exit
编译器可以很大程度上改变你的代码如何,只要效果类似于你要求的。在这种情况下,它有效地将代码重写为:
A compiler can pretty much transform your code how it wants, as long as the effect is similar to what you asked for. In this case, it has effectively rewritten the code as:
int main(int argc, char**argv) {
if (argc != 0)
{
int i = 0;
if (argc % 2) {
do {
foo(argv[1]);
++i;
} while (i != argc);
} else {
do {
foo(argv[0]);
++i;
} while (i != argc);
}
}
return 0;
}
这是Loop Invariant Optimization的一种形式,计算条件如果循环不会被执行。
It's a form of Loop Invariant Optimization, combined here with a first check to avoid computing the condition if the loop is not going to get executed.
对于那些认为第一个解决方案更清楚的人,我们很高兴有编译器为我们做细致的优化!
For those of us who would think the first solution is clearer, we're quite happy to have the compiler do the nitty gritty optimization for us!
这篇关于gcc是否优化我的循环条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!