请问GCC优化我的状态周期? [英] Does gcc optimize my cycle with condition?

查看:109
本文介绍了请问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
    }
}

假设:一个周期,如果没有条件快于符合条件。 (这是真的?)
问:请问gcc的因素了我的如果,如果条件已设置外的周期,周期本身没有按碰条件

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?

如果不是这样,我应该切换如果,复制code,违反干燥,等等。

If not, I should switch the if and the for, duplicate code, violate DRY, etc.

推荐答案

对于那些谁不希望阅读冗长的文章,这种优化称为(LLVM中)的Loop Unswitch

For those who don't wish to read a lengthy post, this optimization is called (in LLVM) Loop Unswitch.

为什么不问一个编译器?

Why not ask a compiler ?

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

转化为SSA形式(通过 LLVM尝试):

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:


  • 输入:检查 ARGC 等于0,如果是,转到 BB5 (退出),否则转到 bb.nph

  • bb.nph :计算值条件,如果这是真的,转到 bb3.us 否则转到 BB3

  • bb3.us BB3 :分别为循环真假条件

  • BB5 :退出

  • entry: check if argc is equal to 0, if it is, go to bb5 (exit) else go to bb.nph
  • bb.nph: compute the value of condition, if it's true, go to bb3.us else go to bb3
  • bb3.us and bb3: loops for the true and false condition respectively
  • bb5: exit

一个编译器pretty怎么想,只要效果类似于你问什么太大改变你的code。在这种情况下,它有效地改写了code为:

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

这是循环不变量优化的一种形式,与第一次检查,以避免计算如果循环不会得到执行的情况在这里结合起来。

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优化我的状态周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆