编译器是否会通过将循环中的条件语句移动来优化循环中的条件语句?

sol*_*wzs 8 c optimization gcc

这是C代码:

struct node{
    void *value;
    struct node *next;
};

void g(void *p){
    /*...*/
}

void f(struct node *head, const int ok){
    struct node *p=head;

    while (p){
        /* ...
           code 1 
           ...
         */
        if (ok!=0){
            g(p->value);
        }
        p=p->next;
    }
}
Run Code Online (Sandbox Code Playgroud)

我用gcc来编译这段代码.如果我编译-O,它会优化这样的功能f:

void f(struct node *head, const int ok){
    struct node *p=head;

    if (ok!=0){
        while (p){
            /* ...
               code 1 
               ...
             */
            g(p->value);
            p=p->next;
        }
    }
    else{
        while (p){
            /* ...
               code 1 
               ...
             */
            p=p->next;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*baz 15

这在很大程度上取决于有多大/* code 1 */.如果它非常小,它可能会.但如果它超过几行,它很可能不会.为每个单元复制大量代码if会对性能产生可怕的影响.事实上,这可能发生在非常积极的优化中,当然不仅仅是-O.从gcc(强调我的)手册页:

-O
-O1 ......

使用-O,编译器会尝试减少代码大小执行时间,而不执行任何需要大量编译时间的优化.

因此减少代码也是优化的一部分.

-O2优化甚至更多.GCC几乎执行所有支持的优化,不涉及空速 - 权衡.与-O相比,此选项增加了编译时间和生成代码的性能.

所以-O2也不会做你想要的.

-O3优化更多.-O3开启所有-O2指定的优化并开启内-finline-functions,-funswitch-loops,-fpredictive-commoning, -fgcse-after-reload,-ftree-vectorize-fipa-cp-clone选项.

现在我们必须查看这些选项,看看它们中是否有任何可能符合您的要求:

-funswitch-loops
将具有循环不变条件的分支移出循环,在两个分支上重复循环(根据条件的结果进行修改).

瞧!随着-O3您获得您想要的优化.