2

我一直在阅读 Scott Meyers 的Effective C++,更具体地说是关于内联的第 30 条。

所以我写了以下内容,试图用 gcc 4.6.3 进行优化

// test.h
class test {
public:

    inline int max(int i) { return i > 5 ? 1 : -1; }
    int foo(int);

private:
   int d;
};

// test.cpp

int test::foo(int i) { return max(i); }

// main.cpp

#include "test.h"

int main(int argc, const char *argv[]) {
    test t;
    return t.foo(argc);
}

并使用以下替代方法生成相关组件:

g++ -S -I. test.cpp main.cpp
g++ -finline-functions -S -I. test.cpp main.cpp

就内联方法而言,这两个命令都生成了相同的程序集;我可以看到max()方法体(也有一个cmpl语句和相关的跳转)及其从foo().

我错过了一些非常明显的东西吗?我不能说我浏览了 gcc 手册页,但找不到任何相关的突出内容。

所以,我只是将-O3默认情况下内联优化的优化级别提高到了,根据:

g++ -c -Q -O3 --help=optimizers | grep inline
  -finline-functions                    [enabled]
  -finline-functions-called-once        [enabled]
  -finline-small-functions              [enabled] 

不幸的是,这个优化的(如预期的那样)上面的代码片段几乎不存在了。 max()不再存在(至少作为显式标记的装配块)并且foo()已减少为:

_ZN4test3fooEi:
.LFB7:
.cfi_startproc
rep
ret
.cfi_endproc

我目前无法清楚地理解(并且超出了研究范围)。

理想情况下,我希望看到的是块max()内部的汇编代码。foo()有没有办法(通过命令行选项或使用不同的(非平凡的?)代码片段)来产生这样的输出?

4

1 回答 1

3

即使您不要求,编译器也可以完全自由地内联函数 - 无论您是否使用inline关键字,或者无论您是否使用-finline-functions(尽管如果您使用可能不会-fnoinline-functions- 这与您的要求相反,尽管 C++ 标准没有这样说,但如果它不做它所说的事情,标志就会变得毫无意义)。

接下来,编译器也不总是确定您的函数不会在“其他地方”使用,因此它将生成大多数内联函数的外联副本,除非完全清楚它“不可能被调用从其他地方[例如,该类被声明为无法在其他地方访问]。

如果你不使用函数的结果,并且函数没有副作用(例如写入全局变量、执行 I/O 或调用函数,编译器“不知道它做了什么” ),那么编译器会将该代码消除为“死” - 因为您真的不想要不必要的代码,是吗?在你的函数return前面添加一个应该会有所帮助。max(i)foo

于 2014-08-12T21:57:21.163 回答