GNU 编译器优化

问题描述 投票:0回答:4

我对编译器了解不多,但知道它们足够复杂和智能,可以优化你的代码。 假设我的代码如下所示:

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

GNU 编译器是否足够聪明,能够意识到

foo
的长度在此循环过程中不会改变,并用正确的值替换
foo.length()
调用? 或者每次
foo.length()
比较都会调用
i

c++ gcc optimization
4个回答
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;
}

我将上面的代码保存在test.cpp中并这样编译:

$ clang++ -o test.o -Os -c test.cpp

-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

就像Mysticial说的;这只是一个变量访问。


6
投票

唯一确定的方法就是尝试并查看装配。

我的猜测是,如果对

length()
的调用是内联的,那么 Loop Invariant Code Motion 会将
length()
的内部提升到循环之外,并将其替换为单个变量。

再想一想,这甚至可能没有实际意义。字符串的大小可能只是

string
类中的一个简单字段 - 它位于堆栈上。因此,仅内联对
length()
的调用就已经具有减少对简单变量访问的调用的效果。

编辑: 在后一种情况下,循环内是否修改

foo
的长度甚至并不重要。获取字符串的长度已经只是一个变量访问了。


2
投票

编译器必须保证程序的行为就好像

length()
在每一轮中都被调用一样。只有当它能够证明没有副作用并且结果确实是恒定的时,它才能将调用提升到循环之外。

实际例子中发生的情况需要具体情况具体分析。如果你好奇的话,就看一下装配吧。

强制提升的典型方法是手动执行:

for (unsigned int i = 0, end = s.length(); i != end; ++i)

也许您还想考虑现代的

for (char & c : s)
作为替代方案。


0
投票

老实说,我不知道 gcc 会如何优化这段代码。但将冗余代码移到循环外称为“部分冗余消除”。将 foo.length() 移到循环之外,称为循环不变代码移动,是部分冗余消除的一种形式。请看一下龙书第9.5节(我也在读这一章),它详细阐述了如何使用数据流分析来解决此类问题。这是斯坦福大学的幻灯片:http://suif.stanford.edu/~courses/cs243/lectures/l5.pdf。希望这些能有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.