可以链接器内联函数? [英] Can the linker inline functions?

查看:177
本文介绍了可以链接器内联函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在文件 file1.c中,有一个是在文件中实现的函数调用 file2.c中
当我链接 file1.o file2.o 成可执行文件,如果功能文件2 是非常小的,将连接器自动检测功能小,内联呼吁?

In the file file1.c, there is a call to a function that is implemented in the file file2.c. When I link file1.o and file2.o into an executable, if the function in file2 is very small, will the linker automatically detect that the function is small and inline its call?

推荐答案

在除了为链接时code一代詹姆斯McNellis提到(LTCG)的支持下,GCC工具链也支持链接时优化。与4.5版本开始,GCC支持 -flto 开关使链接时优化(LTO),整个程序优化的形式,从不同的对象文件让它内联函数(和任何其他优化编译器可能能够使如果它被编译所有的目标文件,好像他们是从一个单一的C源文件)。

In addition to the support for Link Time Code Generation (LTCG) that Jame McNellis mentioned, the GCC toolchain also supports link time optimization. Starting with version 4.5, GCC supports the -flto switch which enables Link Time Optimization (LTO), a form of whole program optimization that lets it inline functions from separate object files (and whatever other optimizations a compiler might be able to make if it were compiling all the object files as if they were from a single C source file).

下面是一个简单的例子:

Here's a simple example:

test.c以

void print_int(int x);

int main(){
    print_int(1);
    print_int(42);
    print_int(-1);

    return 0;
}

print_int.c

#include <stdio.h>

void print_int( int x)
{
    printf( "the int is %d\n", x);
}

首先使用GCC4.5.x编译它们 - 从GCC文档示例中使用 -O2 ,但让我简单的测试明显的效果,我不得不使用 -O3

First compile them using GCC4.5.x - examples from GCC docs use -O2, but to get visible results in my simple test, I had to use -O3:

C:\temp>gcc --version
gcc (GCC) 4.5.2

# compile with preparation for LTO
C:\temp>gcc -c -O3 -flto test.c
C:\temp>gcc -c -O3 -flto print_int.c

# link without LTO
C:\temp>gcc -o test-nolto.exe  print_int.o test.o

要得到你应该甚至在链接阶段使用的优化选项LTO的效果 - 连接器实际上是调用编译器来编译中间code片,编译器放入对象文件中的第一上述步骤。如果你没有在这个阶段通过优化选项以及,编译器将不执行,你会寻找的内联。

To get the effect of LTO you're supposed to use the optimization options even at the link stage - the linker actually invokes the compiler to compile pieces of intermediate code that the compiler put into the object file in the first steps above. If you don't pass the optimization option at this stage as well, the compiler won't perform the inlining that you'd be looking for.

# link using LTO
C:\temp>gcc -o test-lto.exe -flto -O3 print_int.o test.o

无链接时优化版本拆卸。请注意,调用到 print_int()函数取得:

C:\temp>gdb test-nolto.exe
GNU gdb (GDB) 7.2
(gdb) start
Temporary breakpoint 1 at 0x401373
Starting program: C:\temp/test-nolto.exe
[New Thread 3324.0xdc0]

Temporary breakpoint 1, 0x00401373 in main ()
(gdb) disassem
Dump of assembler code for function main:
   0x00401370 <+0>:     push   %ebp
   0x00401371 <+1>:     mov    %esp,%ebp
=> 0x00401373 <+3>:     and    $0xfffffff0,%esp
   0x00401376 <+6>:     sub    $0x10,%esp
   0x00401379 <+9>:     call   0x4018ca <__main>
   0x0040137e <+14>:    movl   $0x1,(%esp)
   0x00401385 <+21>:    call   0x401350 <print_int>
   0x0040138a <+26>:    movl   $0x2a,(%esp)
   0x00401391 <+33>:    call   0x401350 <print_int>
   0x00401396 <+38>:    movl   $0xffffffff,(%esp)
   0x0040139d <+45>:    call   0x401350 <print_int>
   0x004013a2 <+50>:    xor    %eax,%eax
   0x004013a4 <+52>:    leave
   0x004013a5 <+53>:    ret

与链接时优化版本拆卸。请注意,调用的printf()应直接:

C:\temp>gdb test-lto.exe

GNU gdb (GDB) 7.2
(gdb) start
Temporary breakpoint 1 at 0x401373
Starting program: C:\temp/test-lto.exe
[New Thread 1768.0x126c]

Temporary breakpoint 1, 0x00401373 in main ()
(gdb) disassem
Dump of assembler code for function main:
   0x00401370 <+0>:     push   %ebp
   0x00401371 <+1>:     mov    %esp,%ebp
=> 0x00401373 <+3>:     and    $0xfffffff0,%esp
   0x00401376 <+6>:     sub    $0x10,%esp
   0x00401379 <+9>:     call   0x4018da <__main>
   0x0040137e <+14>:    movl   $0x1,0x4(%esp)
   0x00401386 <+22>:    movl   $0x403064,(%esp)
   0x0040138d <+29>:    call   0x401acc <printf>
   0x00401392 <+34>:    movl   $0x2a,0x4(%esp)
   0x0040139a <+42>:    movl   $0x403064,(%esp)
   0x004013a1 <+49>:    call   0x401acc <printf>
   0x004013a6 <+54>:    movl   $0xffffffff,0x4(%esp)
   0x004013ae <+62>:    movl   $0x403064,(%esp)
   0x004013b5 <+69>:    call   0x401acc <printf>
   0x004013ba <+74>:    xor    %eax,%eax
   0x004013bc <+76>:    leave
   0x004013bd <+77>:    ret
End of assembler dump.

和这里的相同实验MSVC(先用LTCG):

And here's the same experiment with MSVC (first with LTCG):

C:\temp>cl -c /GL /Zi /Ox test.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c

C:\temp>cl -c /GL /Zi /Ox print_int.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

print_int.c

C:\temp>link /LTCG test.obj print_int.obj /out:test-ltcg.exe /debug
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Generating code
Finished generating code

C:\temp>"\Program Files (x86)\Debugging Tools for Windows (x86)"\cdb test-ltcg.exe

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: test-ltcg.exe
    // ...
0:000> u main
*** WARNING: Unable to verify checksum for test-ltcg.exe
test_ltcg!main:
00cd1c20 6a01            push    1
00cd1c22 68d05dcd00      push    offset test_ltcg!__decimal_point_length+0x10 (00cd5dd0)
00cd1c27 e8e3f3feff      call    test_ltcg!printf (00cc100f)
00cd1c2c 6a2a            push    2Ah
00cd1c2e 68d05dcd00      push    offset test_ltcg!__decimal_point_length+0x10 (00cd5dd0)
00cd1c33 e8d7f3feff      call    test_ltcg!printf (00cc100f)
00cd1c38 6aff            push    0FFFFFFFFh
00cd1c3a 68d05dcd00      push    offset test_ltcg!__decimal_point_length+0x10 (00cd5dd0)
00cd1c3f e8cbf3feff      call    test_ltcg!printf (00cc100f)
00cd1c44 83c418          add     esp,18h
00cd1c47 33c0            xor     eax,eax
00cd1c49 c3              ret
0:000>

现在没有LTCG。请注意,MSVC,你必须从执行LTCG编译.c文件,而不 / GL 来prevent连接器 - 否则,链接器检测到 / GL 指定,它会迫使 / LTCG 选项(嘿,这是你说的,你用<诚征各地在第一时间code> / GL )

Now without LTCG. Note that with MSVC you have to compile the .c file without the /GL to prevent the linker from performing LTCG - otherwise the linker detects that /GL was specified, and it'll force the /LTCG option (hey, that's what you said you wanted the first time around with /GL):

C:\temp>cl -c /Zi /Ox test.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c

C:\temp>cl -c /Zi /Ox print_int.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

print_int.c

C:\temp>link test.obj print_int.obj /out:test-noltcg.exe /debug
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

C:\temp>"\Program Files (x86)\Debugging Tools for Windows (x86)"\cdb test-noltcg.exe

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: test-noltcg.exe
// ...
0:000> u main
test_noltcg!main:
00c41020 6a01            push    1
00c41022 e8e3ffffff      call    test_noltcg!ILT+5(_print_int) (00c4100a)
00c41027 6a2a            push    2Ah
00c41029 e8dcffffff      call    test_noltcg!ILT+5(_print_int) (00c4100a)
00c4102e 6aff            push    0FFFFFFFFh
00c41030 e8d5ffffff      call    test_noltcg!ILT+5(_print_int) (00c4100a)
00c41035 83c40c          add     esp,0Ch
00c41038 33c0            xor     eax,eax
00c4103a c3              ret
0:000>

一件事,微软的链接器在LTCG <击>支持不支持GCC(据我所知)是档案导引优化(PGO)。这种技术允许基于从程序的previous运行聚集了分析数据微软的链接器优化。这使得连接器做的事情,如收集'热'功能集成到同一个内存页和很少使用code序列到其他内存页,以减少工作集的节目。

One thing that Microsoft's linker supports in LTCG that is not supported by GCC (as far as I know) is Profile Guided Optimization (PGO). That technology allows Microsoft's linker to optimize based on a profiling data gathered from previous runs of the program. This allows the linker to do things such as gather 'hot' functions onto the same memory pages and seldom used code sequences onto other memory pages to reduce the working set of a program.

&NBSP;

编辑(2011年8月28日):GCC支持情景使用选项,如导引优化-fprofile生成 -fprofile使用,但我完全不了解他们。

Edit (28 Aug 2011): GCC support profile guided optimization using such options as -fprofile-generate and -fprofile-use, but I'm completely uninformed about them.

感谢康拉德·鲁道夫指出这一点给我。

Thanks to Konrad Rudolph for pointing this out to me.

这篇关于可以链接器内联函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆