将编译器通过将条件语句移出循环来优化循环中的条件语句



下面是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;
    }
}

我使用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;
        }
    }
}

这很大程度上取决于/* 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,你可以得到你想要的优化

嗯,这取决于很多事情。

由于您使用的是gcc,因此您总是可以通过调用gcc -o -S fileName.c

来检查它是否为特定程序执行了操作。

在这种情况下,我发现这个网站http://gcc.godbolt.org/非常有用

最新更新