GNU编译器优化

Hig*_*ife 3 c++ compiler-construction optimization gcc

我对编译器知之甚少,但知道它们很复杂,足够聪明,可以优化代码.假设我的代码看起来像这样:

 string foo = "bar";
 for(int i = 0; i < foo.length(); i++){
     //some code that does not modify the length of foo
 }
Run Code Online (Sandbox Code Playgroud)

GNU编译器是否足够聪明,可以意识到在foo此循环过程中长度不会改变并用foo.length()适当的值替换调用?或者会foo.length()被称为每次i比较?

Jam*_*mes 7

由于Mysticial和Kerrek都正确地建议在生成的程序集中窥视,这里有一个例子:

#include <string>
using namespace std;

int does_clang_love_me(string foo) {
    int j = 0;
    for (int i = 0; i < foo.length(); i++) {
        j++;
    }
    return j;
}
Run Code Online (Sandbox Code Playgroud)

我在test.cpp中保存了上面的代码并将其编译为:

$ clang++ -o test.o -Os -c test.cpp
Run Code Online (Sandbox Code Playgroud)

-Os开关告诉clang尝试针对最小的代码大小进行优化.GCC有一个你可以使用的相应开关.为了查看程序集,我用otool命中了生成的目标文件,因为我此刻碰巧正在使用mac.其他平台也有类似的工具.

$ otool -tv test.o

test.o:
(__TEXT,__text) section
__Z16does_clang_love_meSs:
0000000000000000    pushq   %rbp
0000000000000001    movq    %rsp,%rbp
0000000000000004    movq    (%rdi),%rax
0000000000000007    movq    0xe8(%rax),%rcx
000000000000000b    xorl    %eax,%eax
000000000000000d    testq   %rcx,%rcx
0000000000000010    je  0x0000001e
0000000000000012    cmpq    $0x01,%rcx
0000000000000016    movl    $0x00000001,%eax
000000000000001b    cmoval  %ecx,%eax
000000000000001e    popq    %rbp
000000000000001f    ret
Run Code Online (Sandbox Code Playgroud)

就像Mysticial说的那样; 它只是一个可变访问.


Mys*_*ial 6

确切知道的唯一方法是尝试并看看装配.

我的猜测是,如果length()内联调用,那么Loop Invariant Code Motion将提升length()循环内部的内部并用单个变量替换它.

作为第二个想法,这甚至可能没有实际意义.字符串的大小可能只是类中的一个简单字段string- 它位于堆栈中.因此,只是内联调用length()已经具有减少对简单变量访问的调用的效果.

编辑: 在后一种情况下,foo在循环内是否修改了长度也无关紧要.获取字符串的长度只是一个变量访问.