冗余分配消除是否相当典型的优化?

时间:2013-01-23 14:08:23

标签: c compiler-construction compiler-optimization

鉴于以下内容:

len = strlen(str);
/* code that does not read from len */
len = new_len;

我可以依赖编译器删除第一行吗?

我正在编写代码生成脚本。第一行是在一个地方生成的,而后面的所有内容都是在其他地方生成的(通过后代类中的虚函数)。大多数时候,不需要len。有时虽然如此。我想知道我是否可以在所有情况下都设置它,如果不需要,让编译器摆脱它。

4 个答案:

答案 0 :(得分:4)

不,当然你不能“依赖”编译器完成的优化选择。

它们可以根据用户的奇思妙想(编译器命令行选项)或使用不同的编译器版本进行更改。

由于语言标准不要求您描述的行为,因此您不能依赖编译器来实现它。

另一方面,你可以测试它,并尝试“哄”它进行优化,例如(再次)要求你的编译器做尽可能多的优化,例如。

答案 1 :(得分:2)

编译器非常聪明。但依靠编译器删除"未使用"函数调用可能不是一个好主意。首先,编译器需要理解你正在调用的函数(因此strlen是一个很好的例子,因为大多数编译器都了解strlen的作用以及它如何影响其他事物) - 如果函数不是编译器的那个&# 34;理解"然后它无法优化它。

如果您这样做了:

 x = printf("Hello, World!\n");

 x = printf("World, Hello!\n");

您是否认为他们的编译器通过删除第一个printf做了正确的事情?可能不是......所以,使用任何函数,编译器都无法确定"是无副作用的",编译器必须调用该函数,即使结果未被使用。无副作用意味着在正常情况下 - 例如使用无效指针调用strlen()会产生副作用 - 您的代码可能会崩溃 - 但这不是"正常情况" - 使用strlen()只是为了检查你的指针是否有效,对吗?

因此,换句话说,您可能希望确保在调用strlen之前确实需要调用strlen() - 或者考虑到编译器可能会生成不必要的strlen调用。

答案 2 :(得分:1)

现代编译器似乎在消除冗余分配方面做得非常出色。我通过VS 2008和gcc 4.6运行了以下片段,并且实际上删除了对strlen(内联代码)的调用。两个编译器都设法看到something()something_else()都没有副作用。对这些的调用也会被删除。

这发生在VC中的/ O1和gcc中的/ O1中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int something(int len)  {
    if(len != len) {
        printf("%d\n", len);
    }
    return 0;
}

int something_else(int len) {
    return len * len;
}

int main(void) {
    char *s = malloc(1000);
    size_t len;
    strcpy(s, "Hello world");
    len = strlen(s);
    something(len);
    printf("%s\n", s);
    len += 8;
    something_else(len);
    len = 5;
    printf("%d\n", len);
    return 0;
}

答案 3 :(得分:0)

这取决于编译器和&amp;您指定的优化级别。

这里最初从函数调用中分配。如果该功能有副作用怎么办?
所以你不能只假设编译器为你优化它。

如果初始转让声明没有任何副作用,你指定优化级别足够好(例如gcc的情况下为-O3),它可以为你优化它。