gcc能否根据条件优化我的周期?

我有以下周期:

//condition will be set here to true or false for (int i = 0; i < LARGE_NUMBER; i++) { if (condition) { //do foo } else { //do bar } } 

假设:没有条件而不是条件的周期更快。 (这是真的吗?)问题:如果condition已经设置在for循环之外,并且循环本身没有触及condition ,那么gcc会将我的if ,if

如果没有,我应该切换iffor ,重复代码,违反DRY等。

对于那些不想阅读冗长post的人来说,这种优化称为(在LLVM中) Loop Unswitch 。

为什么不问编译器?

 void foo(char* c); int main(int argc, char **argv) { bool const condition = argc % 2; for (int i = 0; i != argc; ++i) { if (condition) { foo(argv[1]); } else { foo(argv[0]); } } return 0; } 

转换为SSAforms(通过LLVM试用 ):

 define i32 @main(i32 %argc, i8** nocapture %argv) { entry: %0 = icmp eq i32 %argc, 0 ;  [#uses=1] br i1 %0, label %bb5, label %bb.nph bb.nph: ; preds = %entry %1 = and i32 %argc, 1 ;  [#uses=1] %toBool = icmp eq i32 %1, 0 ;  [#uses=1] %2 = getelementptr inbounds i8** %argv, i64 1 ;  [#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 ] ;  [#uses=1] %3 = load i8** %argv, align 8 ;  [#uses=1] tail call void @_Z3fooPc(i8* %3) %4 = add nsw i32 %i.07.us, 1 ;  [#uses=2] %exitcond = icmp eq i32 %4, %argc ;  [#uses=1] br i1 %exitcond, label %bb5, label %bb3.us bb3: ; preds = %bb3, %bb.nph %i.07 = phi i32 [ %6, %bb3 ], [ 0, %bb.nph ] ;  [#uses=1] %5 = load i8** %2, align 8 ;  [#uses=1] tail call void @_Z3fooPc(i8* %5) %6 = add nsw i32 %i.07, 1 ;  [#uses=2] %exitcond8 = icmp eq i32 %6, %argc ;  [#uses=1] br i1 %exitcond8, label %bb5, label %bb3 bb5: ; preds = %bb3, %bb3.us, %entry ret i32 0 } 

也许不太可读,所以让我指出这里有什么:

  • entry :检查argc是否等于0,如果是,转到bb5 (退出)否则转到bb.nph
  • bb.nph :计算condition的值,如果是真的,转到bb3.us else转到bb3.us
  • bb3.usbb3.us :分别为true和false条件循环
  • bb5 :退出

只要效果类似于您要求的效果,编译器几乎可以根据需要转换代码。 在这种情况下,它有效地将代码重写为:

 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; } 

它是循环不变优化的一种forms,这里结合第一次检查以避免在循环不会被执行时计算条件。

对于我们这些认为第一个解决方案更清晰的人来说,我们很高兴让编译器为我们进行细节优化!

如果在迭代期间可以certificatecondition不会改变,那么任何体面的优化编译器都会这样做。

此外,即使编译器实际上没有这样做,您也可以支持您使用分析中的硬数据将代码重写为不太人类可读的forms的决定。 不要过早优化。 给代码的读者一个“嗯?”是不值得的。 为了减少几毫秒(和“读者”肯定包括你自己在未来的时间)的时刻。

我不主张通过通常的“过早优化”论点采取任何行动。 保持代码清晰是最重要的,如果整个程序太慢,您可能想要在程序彻底调试后分析并找到实际的瓶颈(通常无法猜测)。

即使编译器没有为您优化此特定情况,您可能想知道CPU执行某种forms的分支预测 ,这将大大减少在条件可预测的情况下处理条件所需的时间。

实际上, 管道中的大多数CPU处理指令以及必须确定跳转地址时,条件变量可能是未知的。 这将导致流水线停滞 ,这是大多数现代处理器试图猜测(事实上聪明)程序将跳转的地方。 如果条件变量确实已知(就像你的情况那样),猜测将是完美的。

所以我怀疑即使使用“哑”编译器,你也会看到这两个选项之间存在差异,至少在现代机器上是这样。