Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 链接器是否可以内联函数?_C_Optimization_Linker_Inline - Fatal编程技术网

C 链接器是否可以内联函数?

C 链接器是否可以内联函数?,c,optimization,linker,inline,C,Optimization,Linker,Inline,在文件file1.c中,调用了在文件file2.c中实现的函数。 当我将file1.o和file2.o链接到一个可执行文件中时,如果file2中的函数非常小,链接器是否会自动检测到该函数很小并内联其调用?除了Jame McNell提到的对链接时间代码生成(LTCG)的支持之外,GCC工具链还支持链接时间优化。从4.5版开始,GCC支持-flto开关,该开关启用链接时间优化(LTO),这是一种全程序优化形式,允许它从单独的目标文件内联函数(如果编译器编译所有的对象文件,就好像它们来自一个C源文件一

在文件
file1.c
中,调用了在文件
file2.c
中实现的函数。
当我将
file1.o
file2.o
链接到一个可执行文件中时,如果
file2
中的函数非常小,链接器是否会自动检测到该函数很小并内联其调用?

除了Jame McNell提到的对链接时间代码生成(LTCG)的支持之外,GCC工具链还支持链接时间优化。从4.5版开始,GCC支持
-flto
开关,该开关启用链接时间优化(LTO),这是一种全程序优化形式,允许它从单独的目标文件内联函数(如果编译器编译所有的对象文件,就好像它们来自一个C源文件一样,那么它可以进行任何其他优化)

下面是一个简单的例子:

测试.c

void print_int(int x);

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

    return 0;
}
#include <stdio.h>

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

void print_int(int x);

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

    return 0;
}
#include <stdio.h>

void print_int( int x)
{
    printf( "the int is %d\n", x);
}
为了获得LTO的效果,即使在链接阶段,你也应该使用优化选项——链接器实际上调用编译器来编译编译器在上面的第一步中放入目标文件的中间代码。如果你在这个阶段没有通过优化选项,编译器将不会执行in你要找的衬里

# link using LTO
C:\temp>gcc -o test-lto.exe -flto -O3 print_int.o test.o
在没有链接时间优化的情况下反汇编版本。请注意,调用的是
print\u 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
下面是MSVC的相同实验(首先是LTCG):

现在没有LTCG。请注意,使用MSVC,您必须在不使用
/GL
的情况下编译.c文件,以防止链接器执行LTCG-否则链接器会检测到指定了
/GL
,它将强制执行
/LTCG
选项(嘿,这就是您第一次使用
/GL
时想要的):

微软的链接器在LTCG中支持的一件事是GCC不支持的(据我所知),那就是配置文件引导优化(PGO)。该技术允许Microsoft的链接器根据从以前运行的程序中收集的分析数据进行优化。这允许链接器在同一内存页上收集“热”函数,并在其他内存页上收集很少使用的代码序列,以减少程序的工作集


编辑(2011年8月28日):GCC支持使用
-fprofile-generate
-fprofile-use
等选项进行概要文件引导优化,但我对此一无所知


感谢Konrad Rudolph向我指出这一点。

除了Jame McNell提到的对链接时间代码生成(LTCG)的支持外,GCC工具链还支持链接时间优化。从4.5版开始,GCC支持启用链接时间优化(LTO)的-flto开关,这是一种全程序优化形式,允许它从单独的目标文件内联函数(如果编译器将所有目标文件编译为一个C源文件,则可以进行任何其他优化)

下面是一个简单的例子:

测试.c

void print_int(int x);

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

    return 0;
}
#include <stdio.h>

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

void print_int(int x);

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

    return 0;
}
#include <stdio.h>

void print_int( int x)
{
    printf( "the int is %d\n", x);
}
为了获得LTO的效果,即使在链接阶段,你也应该使用优化选项——链接器实际上调用编译器来编译编译器在上面的第一步中放入目标文件的中间代码。如果你在这个阶段没有通过优化选项,编译器将不会执行in你要找的衬里

# link using LTO
C:\temp>gcc -o test-lto.exe -flto -O3 print_int.o test.o
在没有链接时间优化的情况下反汇编版本。请注意,调用的是
print\u 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
下面是MSVC的相同实验(首先是LTCG):

现在没有LTCG。请注意,使用MSVC,您必须在不使用
/GL
的情况下编译.c文件,以防止链接器执行LTCG-否则链接器会检测到指定了
/GL
,它将强制执行
/LTCG
选项(嘿,这就是您第一次使用
/GL
时想要的):

微软的链接器在LTCG中支持的一件事是GCC不支持的(据我所知),那就是配置文件引导优化(PGO)。该技术允许Microsoft的链接器根据从以前运行的程序中收集的分析数据进行优化。这允许链接器在同一内存页上收集“热”函数,并在其他内存页上收集很少使用的代码序列,以减少程序的工作集


编辑(2011年8月28日):GCC支持使用
-fprofile-generate
-fprofile-use
等选项进行概要文件引导优化,但我对此一无所知


感谢Konrad Rudolph指出这一点。

一些链接器可以,是的(VisualC++链接器有一个叫做链接时间代码生成的特性”,它执行交叉模块内联和优化。不管你使用的链接器是否可以,都不可能说,因为你还没有告诉我们你使用的链接器。(即使如此,唯一真正知道的方法是找出链接器生成的代码……)一些链接器可以,是的(VisualC++链接器有一个称为“链接时间代码生成”的特性,它执行跨模块内联和优化”。。无论您正在使用的链接器是否能够或将实现这一点,都无法确定,因为您尚未告诉我们您正在使用的链接器(即使如此,唯一真正确定的方法是找出您的链接器生成的代码…).GCC还支持PGO,通过
-fprofile generate
-fprofile use
@Konrad:wow-我完全不知道。我必须调查一下。谢谢!但LTO不是由链接器(binutils/ld)处理的;它是一个编译器(GCC/GCC)。@osgx:你说得对,但它实际上是简单的